home *** CD-ROM | disk | FTP | other *** search
Wrap
Text File | 2012-12-14 | 133.8 KB | 4,818 lines
WebInspector.CSSNamedFlowCollectionsView = function() { WebInspector.SidebarView.call(this, WebInspector.SidebarView.SidebarPosition.Left); this.registerRequiredCSS("cssNamedFlows.css"); this._namedFlows = {}; this._contentNodes = {}; this._regionNodes = {}; this.element.addStyleClass("css-named-flow-collections-view"); this.element.addStyleClass("fill"); this._statusElement = document.createElement("span"); this._statusElement.textContent = WebInspector.UIString("CSS Named Flows"); var sidebarHeader = this._leftElement.createChild("div", "tabbed-pane-header selected sidebar-header") var tab = sidebarHeader.createChild("div", "tabbed-pane-header-tab"); tab.createChild("span", "tabbed-pane-header-tab-title").textContent = WebInspector.UIString("CSS Named Flows"); this._sidebarContentElement = this._leftElement.createChild("div", "sidebar-content outline-disclosure"); this._flowListElement = this._sidebarContentElement.createChild("ol"); this._flowTree = new TreeOutline(this._flowListElement); this._emptyElement = document.createElement("div"); this._emptyElement.addStyleClass("info"); this._emptyElement.textContent = WebInspector.UIString("No CSS Named Flows"); this._tabbedPane = new WebInspector.TabbedPane(); this._tabbedPane.closeableTabs = true; this._tabbedPane.show(this._rightElement); } WebInspector.CSSNamedFlowCollectionsView.prototype = { showInDrawer: function() { WebInspector.showViewInDrawer(this._statusElement, this); }, reset: function() { if (!this._document) return; WebInspector.cssModel.getNamedFlowCollectionAsync(this._document.id, this._resetNamedFlows.bind(this)); }, _setDocument: function(document) { this._document = document; this.reset(); }, _documentUpdated: function(event) { var document = (event.data); this._setDocument(document); }, _setSidebarHasContent: function(hasContent) { if (hasContent) { if (!this._emptyElement.parentNode) return; this._sidebarContentElement.removeChild(this._emptyElement); this._sidebarContentElement.appendChild(this._flowListElement); } else { if (!this._flowListElement.parentNode) return; this._sidebarContentElement.removeChild(this._flowListElement); this._sidebarContentElement.appendChild(this._emptyElement); } }, _appendNamedFlow: function(flow) { var flowHash = this._hashNamedFlow(flow.documentNodeId, flow.name); var flowContainer = { flow: flow, flowHash: flowHash }; for (var i = 0; i < flow.content.length; ++i) this._contentNodes[flow.content[i]] = flowHash; for (var i = 0; i < flow.regions.length; ++i) this._regionNodes[flow.regions[i].nodeId] = flowHash; var flowTreeItem = new WebInspector.FlowTreeElement(flowContainer); flowTreeItem.onselect = this._selectNamedFlowTab.bind(this, flowHash); flowContainer.flowTreeItem = flowTreeItem; this._namedFlows[flowHash] = flowContainer; if (!this._flowTree.children.length) this._setSidebarHasContent(true); this._flowTree.appendChild(flowTreeItem); }, _removeNamedFlow: function(flowHash) { var flowContainer = this._namedFlows[flowHash]; if (this._tabbedPane._tabsById[flowHash]) this._tabbedPane.closeTab(flowHash); this._flowTree.removeChild(flowContainer.flowTreeItem); var flow = flowContainer.flow; for (var i = 0; i < flow.content.length; ++i) delete this._contentNodes[flow.content[i]]; for (var i = 0; i < flow.regions.length; ++i) delete this._regionNodes[flow.regions[i].nodeId]; delete this._namedFlows[flowHash]; if (!this._flowTree.children.length) this._setSidebarHasContent(false); }, _updateNamedFlow: function(flow) { var flowHash = this._hashNamedFlow(flow.documentNodeId, flow.name); var flowContainer = this._namedFlows[flowHash]; if (!flowContainer) return; var oldFlow = flowContainer.flow; flowContainer.flow = flow; for (var i = 0; i < oldFlow.content.length; ++i) delete this._contentNodes[oldFlow.content[i]]; for (var i = 0; i < oldFlow.regions.length; ++i) delete this._regionNodes[oldFlow.regions[i].nodeId]; for (var i = 0; i < flow.content.length; ++i) this._contentNodes[flow.content[i]] = flowHash; for (var i = 0; i < flow.regions.length; ++i) this._regionNodes[flow.regions[i].nodeId] = flowHash; flowContainer.flowTreeItem.setOverset(flow.overset); if (flowContainer.flowView) flowContainer.flowView.flow = flow; }, _resetNamedFlows: function(namedFlowCollection) { for (var flowHash in this._namedFlows) this._removeNamedFlow(flowHash); var namedFlows = namedFlowCollection.namedFlowMap; for (var flowName in namedFlows) this._appendNamedFlow(namedFlows[flowName]); if (!this._flowTree.children.length) this._setSidebarHasContent(false); else this._showNamedFlowForNode(WebInspector.panel("elements").treeOutline.selectedDOMNode()); }, _namedFlowCreated: function(event) { if (event.data.documentNodeId !== this._document.id) return; var flow = (event.data); this._appendNamedFlow(flow); }, _namedFlowRemoved: function(event) { if (event.data.documentNodeId !== this._document.id) return; this._removeNamedFlow(this._hashNamedFlow(event.data.documentNodeId, event.data.flowName)); }, _regionLayoutUpdated: function(event) { if (event.data.documentNodeId !== this._document.id) return; var flow = (event.data); this._updateNamedFlow(flow); }, _hashNamedFlow: function(documentNodeId, flowName) { return documentNodeId + "|" + flowName; }, _showNamedFlow: function(flowHash) { this._selectNamedFlowInSidebar(flowHash); this._selectNamedFlowTab(flowHash); }, _selectNamedFlowInSidebar: function(flowHash) { this._namedFlows[flowHash].flowTreeItem.select(true); }, _selectNamedFlowTab: function(flowHash) { var flowContainer = this._namedFlows[flowHash]; if (this._tabbedPane.selectedTabId === flowHash) return; if (!this._tabbedPane.selectTab(flowHash)) { if (!flowContainer.flowView) flowContainer.flowView = new WebInspector.CSSNamedFlowView(flowContainer.flow); this._tabbedPane.appendTab(flowHash, flowContainer.flow.name, flowContainer.flowView); this._tabbedPane.selectTab(flowHash); } }, _selectedNodeChanged: function(event) { var node = (event.data); this._showNamedFlowForNode(node); }, _tabSelected: function(event) { this._selectNamedFlowInSidebar(event.data.tabId); }, _tabClosed: function(event) { this._namedFlows[event.data.tabId].flowTreeItem.deselect(); }, _showNamedFlowForNode: function(node) { if (!node) return; if (this._regionNodes[node.id]) { this._showNamedFlow(this._regionNodes[node.id]); return; } while (node) { if (this._contentNodes[node.id]) { this._showNamedFlow(this._contentNodes[node.id]); return; } node = node.parentNode; } }, wasShown: function() { WebInspector.SidebarView.prototype.wasShown.call(this); WebInspector.domAgent.requestDocument(this._setDocument.bind(this)); WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.DocumentUpdated, this._documentUpdated, this); WebInspector.cssModel.addEventListener(WebInspector.CSSStyleModel.Events.NamedFlowCreated, this._namedFlowCreated, this); WebInspector.cssModel.addEventListener(WebInspector.CSSStyleModel.Events.NamedFlowRemoved, this._namedFlowRemoved, this); WebInspector.cssModel.addEventListener(WebInspector.CSSStyleModel.Events.RegionLayoutUpdated, this._regionLayoutUpdated, this); WebInspector.panel("elements").treeOutline.addEventListener(WebInspector.ElementsTreeOutline.Events.SelectedNodeChanged, this._selectedNodeChanged, this); this._tabbedPane.addEventListener(WebInspector.TabbedPane.EventTypes.TabSelected, this._tabSelected, this); this._tabbedPane.addEventListener(WebInspector.TabbedPane.EventTypes.TabClosed, this._tabClosed, this); }, willHide: function() { WebInspector.domAgent.removeEventListener(WebInspector.DOMAgent.Events.DocumentUpdated, this._documentUpdated, this); WebInspector.cssModel.removeEventListener(WebInspector.CSSStyleModel.Events.NamedFlowCreated, this._namedFlowCreated, this); WebInspector.cssModel.removeEventListener(WebInspector.CSSStyleModel.Events.NamedFlowRemoved, this._namedFlowRemoved, this); WebInspector.cssModel.removeEventListener(WebInspector.CSSStyleModel.Events.RegionLayoutUpdated, this._regionLayoutUpdated, this); WebInspector.panel("elements").treeOutline.removeEventListener(WebInspector.ElementsTreeOutline.Events.SelectedNodeChanged, this._selectedNodeChanged, this); this._tabbedPane.removeEventListener(WebInspector.TabbedPane.EventTypes.TabSelected, this._tabSelected, this); this._tabbedPane.removeEventListener(WebInspector.TabbedPane.EventTypes.TabClosed, this._tabClosed, this); }, __proto__: WebInspector.SidebarView.prototype } WebInspector.FlowTreeElement = function(flowContainer) { var container = document.createElement("div"); container.createChild("div", "selection"); container.createChild("span", "title").createChild("span").textContent = flowContainer.flow.name; TreeElement.call(this, container, flowContainer, false); this._overset = false; this.setOverset(flowContainer.flow.overset); } WebInspector.FlowTreeElement.prototype = { setOverset: function(newOverset) { if (this._overset === newOverset) return; if (newOverset) { this.title.addStyleClass("named-flow-overflow"); this.tooltip = WebInspector.UIString("Overflows."); } else { this.title.removeStyleClass("named-flow-overflow"); this.tooltip = ""; } this._overset = newOverset; }, __proto__: TreeElement.prototype } ; WebInspector.CSSNamedFlowView = function(flow) { WebInspector.View.call(this); this.element.addStyleClass("css-named-flow"); this.element.addStyleClass("outline-disclosure"); this._treeOutline = new TreeOutline(this.element.createChild("ol"), true); this._contentTreeItem = new TreeElement(WebInspector.UIString("content"), null, true); this._treeOutline.appendChild(this._contentTreeItem); this._regionsTreeItem = new TreeElement(WebInspector.UIString("region chain"), null, true); this._regionsTreeItem.expand(); this._treeOutline.appendChild(this._regionsTreeItem); this._flow = flow; var content = flow.content; for (var i = 0; i < content.length; ++i) this._insertContentNode(content[i]); var regions = flow.regions; for (var i = 0; i < regions.length; ++i) this._insertRegion(regions[i]); } WebInspector.CSSNamedFlowView.OversetTypeMessageMap = { empty: "empty", fit: "fit", overset: "overset" } WebInspector.CSSNamedFlowView.prototype = { _createFlowTreeOutline: function(rootDOMNode) { if (!rootDOMNode) return null; var treeOutline = new WebInspector.ElementsTreeOutline(false, false, true); treeOutline.element.addStyleClass("named-flow-element"); treeOutline.setVisible(true); treeOutline.rootDOMNode = rootDOMNode; treeOutline.wireToDomAgent(); WebInspector.domAgent.removeEventListener(WebInspector.DOMAgent.Events.DocumentUpdated, treeOutline._elementsTreeUpdater._documentUpdated, treeOutline._elementsTreeUpdater); return treeOutline; }, _insertContentNode: function(contentNodeId, index) { var treeOutline = this._createFlowTreeOutline(WebInspector.domAgent.nodeForId(contentNodeId)); var treeItem = new TreeElement(treeOutline.element, treeOutline); if (index === undefined) { this._contentTreeItem.appendChild(treeItem); return; } this._contentTreeItem.insertChild(treeItem, index); }, _insertRegion: function(region, index) { var treeOutline = this._createFlowTreeOutline(WebInspector.domAgent.nodeForId(region.nodeId)); treeOutline.element.addStyleClass("region-" + region.regionOverset); var treeItem = new TreeElement(treeOutline.element, treeOutline); var oversetText = WebInspector.UIString(WebInspector.CSSNamedFlowView.OversetTypeMessageMap[region.regionOverset]); treeItem.tooltip = WebInspector.UIString("Region is %s.", oversetText); if (index === undefined) { this._regionsTreeItem.appendChild(treeItem); return; } this._regionsTreeItem.insertChild(treeItem, index); }, get flow() { return this._flow; }, set flow(newFlow) { this._update(newFlow); }, _updateRegionOverset: function(regionTreeItem, newRegionOverset, oldRegionOverset) { var element = regionTreeItem.representedObject.element; element.removeStyleClass("region-" + oldRegionOverset); element.addStyleClass("region-" + newRegionOverset); var oversetText = WebInspector.UIString(WebInspector.CSSNamedFlowView.OversetTypeMessageMap[newRegionOverset]); regionTreeItem.tooltip = WebInspector.UIString("Region is %s." , oversetText); }, _mergeContentNodes: function(oldContent, newContent) { var nodeIdSet = {}; for (var i = 0; i < newContent.length; ++i) nodeIdSet[newContent[i]] = true; var oldContentIndex = 0; var newContentIndex = 0; var contentTreeChildIndex = 0; while(oldContentIndex < oldContent.length || newContentIndex < newContent.length) { if (oldContentIndex === oldContent.length) { this._insertContentNode(newContent[newContentIndex]); ++newContentIndex; continue; } if (newContentIndex === newContent.length) { this._contentTreeItem.removeChildAtIndex(contentTreeChildIndex); ++oldContentIndex; continue; } if (oldContent[oldContentIndex] === newContent[newContentIndex]) { ++oldContentIndex; ++newContentIndex; ++contentTreeChildIndex; continue; } if (nodeIdSet[oldContent[oldContentIndex]]) { this._insertContentNode(newContent[newContentIndex], contentTreeChildIndex); ++newContentIndex; ++contentTreeChildIndex; continue; } this._contentTreeItem.removeChildAtIndex(contentTreeChildIndex); ++oldContentIndex; } }, _mergeRegions: function(oldRegions, newRegions) { var nodeIdSet = {}; for (var i = 0; i < newRegions.length; ++i) nodeIdSet[newRegions[i].nodeId] = true; var oldRegionsIndex = 0; var newRegionsIndex = 0; var regionsTreeChildIndex = 0; while(oldRegionsIndex < oldRegions.length || newRegionsIndex < newRegions.length) { if (oldRegionsIndex === oldRegions.length) { this._insertRegion(newRegions[newRegionsIndex]); ++newRegionsIndex; continue; } if (newRegionsIndex === newRegions.length) { this._regionsTreeItem.removeChildAtIndex(regionsTreeChildIndex); ++oldRegionsIndex; continue; } if (oldRegions[oldRegionsIndex].nodeId === newRegions[newRegionsIndex].nodeId) { if (oldRegions[oldRegionsIndex].regionOverset !== newRegions[newRegionsIndex].regionOverset) this._updateRegionOverset(this._regionsTreeItem.children[regionsTreeChildIndex], newRegions[newRegionsIndex].regionOverset, oldRegions[oldRegionsIndex].regionOverset); ++oldRegionsIndex; ++newRegionsIndex; ++regionsTreeChildIndex; continue; } if (nodeIdSet[oldRegions[oldRegionsIndex].nodeId]) { this._insertRegion(newRegions[newRegionsIndex], regionsTreeChildIndex); ++newRegionsIndex; ++regionsTreeChildIndex; continue; } this._regionsTreeItem.removeChildAtIndex(regionsTreeChildIndex); ++oldRegionsIndex; } }, _update: function(newFlow) { this._mergeContentNodes(this._flow.content, newFlow.content); this._mergeRegions(this._flow.regions, newFlow.regions); this._flow = newFlow; }, __proto__: WebInspector.View.prototype } ; WebInspector.EventListenersSidebarPane = function() { WebInspector.SidebarPane.call(this, WebInspector.UIString("Event Listeners")); this.bodyElement.addStyleClass("events-pane"); this.sections = []; this.settingsSelectElement = document.createElement("select"); this.settingsSelectElement.className = "select-filter"; var option = document.createElement("option"); option.value = "all"; option.label = WebInspector.UIString("All Nodes"); this.settingsSelectElement.appendChild(option); option = document.createElement("option"); option.value = "selected"; option.label = WebInspector.UIString("Selected Node Only"); this.settingsSelectElement.appendChild(option); var filter = WebInspector.settings.eventListenersFilter.get(); if (filter === "all") this.settingsSelectElement[0].selected = true; else if (filter === "selected") this.settingsSelectElement[1].selected = true; this.settingsSelectElement.addEventListener("click", function(event) { event.consume() }, false); this.settingsSelectElement.addEventListener("change", this._changeSetting.bind(this), false); this.titleElement.appendChild(this.settingsSelectElement); this._linkifier = new WebInspector.Linkifier(); } WebInspector.EventListenersSidebarPane._objectGroupName = "event-listeners-sidebar-pane"; WebInspector.EventListenersSidebarPane.prototype = { update: function(node) { RuntimeAgent.releaseObjectGroup(WebInspector.EventListenersSidebarPane._objectGroupName); this._linkifier.reset(); var body = this.bodyElement; body.removeChildren(); this.sections = []; var self = this; function callback(error, eventListeners) { if (error) return; var selectedNodeOnly = "selected" === WebInspector.settings.eventListenersFilter.get(); var sectionNames = []; var sectionMap = {}; for (var i = 0; i < eventListeners.length; ++i) { var eventListener = eventListeners[i]; if (selectedNodeOnly && (node.id !== eventListener.nodeId)) continue; eventListener.node = WebInspector.domAgent.nodeForId(eventListener.nodeId); delete eventListener.nodeId; if (/^function _inspectorCommandLineAPI_logEvent\(/.test(eventListener.handlerBody.toString())) continue; var type = eventListener.type; var section = sectionMap[type]; if (!section) { section = new WebInspector.EventListenersSection(type, node.id, self._linkifier); sectionMap[type] = section; sectionNames.push(type); self.sections.push(section); } section.addListener(eventListener); } if (sectionNames.length === 0) { var div = document.createElement("div"); div.className = "info"; div.textContent = WebInspector.UIString("No Event Listeners"); body.appendChild(div); return; } sectionNames.sort(); for (var i = 0; i < sectionNames.length; ++i) { var section = sectionMap[sectionNames[i]]; body.appendChild(section.element); } } if (node) node.eventListeners(callback); this._selectedNode = node; }, willHide: function() { delete this._selectedNode; }, _changeSetting: function() { var selectedOption = this.settingsSelectElement[this.settingsSelectElement.selectedIndex]; WebInspector.settings.eventListenersFilter.set(selectedOption.value); this.update(this._selectedNode); }, __proto__: WebInspector.SidebarPane.prototype } WebInspector.EventListenersSection = function(title, nodeId, linkifier) { this.eventListeners = []; this._nodeId = nodeId; this._linkifier = linkifier; WebInspector.PropertiesSection.call(this, title); this.propertiesElement.parentNode.removeChild(this.propertiesElement); delete this.propertiesElement; delete this.propertiesTreeOutline; this._eventBars = document.createElement("div"); this._eventBars.className = "event-bars"; this.element.appendChild(this._eventBars); } WebInspector.EventListenersSection.prototype = { addListener: function(eventListener) { var eventListenerBar = new WebInspector.EventListenerBar(eventListener, this._nodeId, this._linkifier); this._eventBars.appendChild(eventListenerBar.element); }, __proto__: WebInspector.PropertiesSection.prototype } WebInspector.EventListenerBar = function(eventListener, nodeId, linkifier) { WebInspector.ObjectPropertiesSection.call(this, WebInspector.RemoteObject.fromPrimitiveValue("")); this.eventListener = eventListener; this._nodeId = nodeId; this._setNodeTitle(); this._setFunctionSubtitle(linkifier); this.editable = false; this.element.className = "event-bar"; this.headerElement.addStyleClass("source-code"); this.propertiesElement.className = "event-properties properties-tree source-code"; } WebInspector.EventListenerBar.prototype = { update: function() { function updateWithNodeObject(nodeObject) { var properties = []; if (this.eventListener.type) properties.push(WebInspector.RemoteObjectProperty.fromPrimitiveValue("type", this.eventListener.type)); if (typeof this.eventListener.useCapture !== "undefined") properties.push(WebInspector.RemoteObjectProperty.fromPrimitiveValue("useCapture", this.eventListener.useCapture)); if (typeof this.eventListener.isAttribute !== "undefined") properties.push(WebInspector.RemoteObjectProperty.fromPrimitiveValue("isAttribute", this.eventListener.isAttribute)); if (nodeObject) properties.push(new WebInspector.RemoteObjectProperty("node", nodeObject)); if (typeof this.eventListener.handlerBody !== "undefined") properties.push(WebInspector.RemoteObjectProperty.fromPrimitiveValue("listenerBody", this.eventListener.handlerBody)); if (this.eventListener.sourceName) properties.push(WebInspector.RemoteObjectProperty.fromPrimitiveValue("sourceName", this.eventListener.sourceName)); if (this.eventListener.location) properties.push(WebInspector.RemoteObjectProperty.fromPrimitiveValue("lineNumber", this.eventListener.location.lineNumber + 1)); this.updateProperties(properties); } WebInspector.RemoteObject.resolveNode(this.eventListener.node, WebInspector.EventListenersSidebarPane._objectGroupName, updateWithNodeObject.bind(this)); }, _setNodeTitle: function() { var node = this.eventListener.node; if (!node) return; if (node.nodeType() === Node.DOCUMENT_NODE) { this.titleElement.textContent = "document"; return; } if (node.id === this._nodeId) { this.titleElement.textContent = node.appropriateSelectorFor(); return; } this.titleElement.removeChildren(); this.titleElement.appendChild(WebInspector.DOMPresentationUtils.linkifyNodeReference(this.eventListener.node)); }, _setFunctionSubtitle: function(linkifier) { if (this.eventListener.location) { this.subtitleElement.removeChildren(); var urlElement; if (this.eventListener.location.scriptId) urlElement = linkifier.linkifyRawLocation(this.eventListener.location); if (!urlElement) { var url = this.eventListener.sourceName; var lineNumber = this.eventListener.location.lineNumber; var columnNumber = 0; urlElement = linkifier.linkifyLocation(url, lineNumber, columnNumber); } this.subtitleElement.appendChild(urlElement); } else { var match = this.eventListener.handlerBody.match(/function ([^\(]+?)\(/); if (match) this.subtitleElement.textContent = match[1]; else this.subtitleElement.textContent = WebInspector.UIString("(anonymous function)"); } }, __proto__: WebInspector.ObjectPropertiesSection.prototype } ; WebInspector.MetricsSidebarPane = function() { WebInspector.SidebarPane.call(this, WebInspector.UIString("Metrics")); WebInspector.cssModel.addEventListener(WebInspector.CSSStyleModel.Events.StyleSheetChanged, this._styleSheetOrMediaQueryResultChanged, this); WebInspector.cssModel.addEventListener(WebInspector.CSSStyleModel.Events.MediaQueryResultChanged, this._styleSheetOrMediaQueryResultChanged, this); WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.AttrModified, this._attributesUpdated, this); WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.AttrRemoved, this._attributesUpdated, this); } WebInspector.MetricsSidebarPane.prototype = { update: function(node) { if (node) this.node = node; this._innerUpdate(); }, _innerUpdate: function() { if (this._isEditingMetrics) return; var node = this.node; if (!node || node.nodeType() !== Node.ELEMENT_NODE) { this.bodyElement.removeChildren(); return; } function callback(style) { if (!style || this.node !== node) return; this._updateMetrics(style); } WebInspector.cssModel.getComputedStyleAsync(node.id, callback.bind(this)); function inlineStyleCallback(style) { if (!style || this.node !== node) return; this.inlineStyle = style; } WebInspector.cssModel.getInlineStylesAsync(node.id, inlineStyleCallback.bind(this)); }, _styleSheetOrMediaQueryResultChanged: function() { this._innerUpdate(); }, _attributesUpdated: function(event) { if (this.node !== event.data.node) return; this._innerUpdate(); }, _getPropertyValueAsPx: function(style, propertyName) { return Number(style.getPropertyValue(propertyName).replace(/px$/, "") || 0); }, _getBox: function(computedStyle, componentName) { var suffix = componentName === "border" ? "-width" : ""; var left = this._getPropertyValueAsPx(computedStyle, componentName + "-left" + suffix); var top = this._getPropertyValueAsPx(computedStyle, componentName + "-top" + suffix); var right = this._getPropertyValueAsPx(computedStyle, componentName + "-right" + suffix); var bottom = this._getPropertyValueAsPx(computedStyle, componentName + "-bottom" + suffix); return { left: left, top: top, right: right, bottom: bottom }; }, _highlightDOMNode: function(showHighlight, mode, event) { event.consume(); var nodeId = showHighlight && this.node ? this.node.id : 0; if (nodeId) { if (this._highlightMode === mode) return; this._highlightMode = mode; WebInspector.domAgent.highlightDOMNode(nodeId, mode); } else { delete this._highlightMode; WebInspector.domAgent.hideDOMNodeHighlight(); } for (var i = 0; this._boxElements && i < this._boxElements.length; ++i) { var element = this._boxElements[i]; if (!nodeId || mode === "all" || element._name === mode) element.style.backgroundColor = element._backgroundColor; else element.style.backgroundColor = ""; } }, _updateMetrics: function(style) { var metricsElement = document.createElement("div"); metricsElement.className = "metrics"; var self = this; function createBoxPartElement(style, name, side, suffix) { var propertyName = (name !== "position" ? name + "-" : "") + side + suffix; var value = style.getPropertyValue(propertyName); if (value === "" || (name !== "position" && value === "0px")) value = "\u2012"; else if (name === "position" && value === "auto") value = "\u2012"; value = value.replace(/px$/, ""); var element = document.createElement("div"); element.className = side; element.textContent = value; element.addEventListener("dblclick", this.startEditing.bind(this, element, name, propertyName, style), false); return element; } function getContentAreaWidthPx(style) { var width = style.getPropertyValue("width").replace(/px$/, ""); if (style.getPropertyValue("box-sizing") === "border-box") { var borderBox = self._getBox(style, "border"); var paddingBox = self._getBox(style, "padding"); width = width - borderBox.left - borderBox.right - paddingBox.left - paddingBox.right; } return width; } function getContentAreaHeightPx(style) { var height = style.getPropertyValue("height").replace(/px$/, ""); if (style.getPropertyValue("box-sizing") === "border-box") { var borderBox = self._getBox(style, "border"); var paddingBox = self._getBox(style, "padding"); height = height - borderBox.top - borderBox.bottom - paddingBox.top - paddingBox.bottom; } return height; } var noMarginDisplayType = { "table-cell": true, "table-column": true, "table-column-group": true, "table-footer-group": true, "table-header-group": true, "table-row": true, "table-row-group": true }; var noPaddingDisplayType = { "table-column": true, "table-column-group": true, "table-footer-group": true, "table-header-group": true, "table-row": true, "table-row-group": true }; var noPositionType = { "static": true }; var boxes = ["content", "padding", "border", "margin", "position"]; var boxColors = [ WebInspector.Color.PageHighlight.Content, WebInspector.Color.PageHighlight.Padding, WebInspector.Color.PageHighlight.Border, WebInspector.Color.PageHighlight.Margin, WebInspector.Color.fromRGBA(0, 0, 0, 0) ]; var boxLabels = [WebInspector.UIString("content"), WebInspector.UIString("padding"), WebInspector.UIString("border"), WebInspector.UIString("margin"), WebInspector.UIString("position")]; var previousBox = null; this._boxElements = []; for (var i = 0; i < boxes.length; ++i) { var name = boxes[i]; if (name === "margin" && noMarginDisplayType[style.getPropertyValue("display")]) continue; if (name === "padding" && noPaddingDisplayType[style.getPropertyValue("display")]) continue; if (name === "position" && noPositionType[style.getPropertyValue("position")]) continue; var boxElement = document.createElement("div"); boxElement.className = name; boxElement._backgroundColor = boxColors[i].toString("original"); boxElement._name = name; boxElement.style.backgroundColor = boxElement._backgroundColor; boxElement.addEventListener("mouseover", this._highlightDOMNode.bind(this, true, name === "position" ? "all" : name), false); this._boxElements.push(boxElement); if (name === "content") { var widthElement = document.createElement("span"); widthElement.textContent = getContentAreaWidthPx(style); widthElement.addEventListener("dblclick", this.startEditing.bind(this, widthElement, "width", "width", style), false); var heightElement = document.createElement("span"); heightElement.textContent = getContentAreaHeightPx(style); heightElement.addEventListener("dblclick", this.startEditing.bind(this, heightElement, "height", "height", style), false); boxElement.appendChild(widthElement); boxElement.appendChild(document.createTextNode(" \u00D7 ")); boxElement.appendChild(heightElement); } else { var suffix = (name === "border" ? "-width" : ""); var labelElement = document.createElement("div"); labelElement.className = "label"; labelElement.textContent = boxLabels[i]; boxElement.appendChild(labelElement); boxElement.appendChild(createBoxPartElement.call(this, style, name, "top", suffix)); boxElement.appendChild(document.createElement("br")); boxElement.appendChild(createBoxPartElement.call(this, style, name, "left", suffix)); if (previousBox) boxElement.appendChild(previousBox); boxElement.appendChild(createBoxPartElement.call(this, style, name, "right", suffix)); boxElement.appendChild(document.createElement("br")); boxElement.appendChild(createBoxPartElement.call(this, style, name, "bottom", suffix)); } previousBox = boxElement; } metricsElement.appendChild(previousBox); metricsElement.addEventListener("mouseover", this._highlightDOMNode.bind(this, false, ""), false); this.bodyElement.removeChildren(); this.bodyElement.appendChild(metricsElement); }, startEditing: function(targetElement, box, styleProperty, computedStyle) { if (WebInspector.isBeingEdited(targetElement)) return; var context = { box: box, styleProperty: styleProperty, computedStyle: computedStyle }; var boundKeyDown = this._handleKeyDown.bind(this, context, styleProperty); context.keyDownHandler = boundKeyDown; targetElement.addEventListener("keydown", boundKeyDown, false); this._isEditingMetrics = true; var config = new WebInspector.EditingConfig(this.editingCommitted.bind(this), this.editingCancelled.bind(this), context); WebInspector.startEditing(targetElement, config); window.getSelection().setBaseAndExtent(targetElement, 0, targetElement, 1); }, _handleKeyDown: function(context, styleProperty, event) { var element = event.currentTarget; function finishHandler(originalValue, replacementString) { this._applyUserInput(element, replacementString, originalValue, context, false); } function customNumberHandler(number) { if (styleProperty !== "margin" && number < 0) number = 0; return number; } WebInspector.handleElementValueModifications(event, element, finishHandler.bind(this), undefined, customNumberHandler); }, editingEnded: function(element, context) { delete this.originalPropertyData; delete this.previousPropertyDataCandidate; element.removeEventListener("keydown", context.keyDownHandler, false); delete this._isEditingMetrics; }, editingCancelled: function(element, context) { if ("originalPropertyData" in this && this.inlineStyle) { if (!this.originalPropertyData) { var pastLastSourcePropertyIndex = this.inlineStyle.pastLastSourcePropertyIndex(); if (pastLastSourcePropertyIndex) this.inlineStyle.allProperties[pastLastSourcePropertyIndex - 1].setText("", false); } else this.inlineStyle.allProperties[this.originalPropertyData.index].setText(this.originalPropertyData.propertyText, false); } this.editingEnded(element, context); this.update(); }, _applyUserInput: function(element, userInput, previousContent, context, commitEditor) { if (!this.inlineStyle) { return this.editingCancelled(element, context); } if (commitEditor && userInput === previousContent) return this.editingCancelled(element, context); if (context.box !== "position" && (!userInput || userInput === "\u2012")) userInput = "0px"; else if (context.box === "position" && (!userInput || userInput === "\u2012")) userInput = "auto"; userInput = userInput.toLowerCase(); if (/^\d+$/.test(userInput)) userInput += "px"; var styleProperty = context.styleProperty; var computedStyle = context.computedStyle; if (computedStyle.getPropertyValue("box-sizing") === "border-box" && (styleProperty === "width" || styleProperty === "height")) { if (!userInput.match(/px$/)) { WebInspector.log("For elements with box-sizing: border-box, only absolute content area dimensions can be applied", WebInspector.ConsoleMessage.MessageLevel.Error, true); return; } var borderBox = this._getBox(computedStyle, "border"); var paddingBox = this._getBox(computedStyle, "padding"); var userValuePx = Number(userInput.replace(/px$/, "")); if (isNaN(userValuePx)) return; if (styleProperty === "width") userValuePx += borderBox.left + borderBox.right + paddingBox.left + paddingBox.right; else userValuePx += borderBox.top + borderBox.bottom + paddingBox.top + paddingBox.bottom; userInput = userValuePx + "px"; } this.previousPropertyDataCandidate = null; var self = this; var callback = function(style) { if (!style) return; self.inlineStyle = style; if (!("originalPropertyData" in self)) self.originalPropertyData = self.previousPropertyDataCandidate; if (typeof self._highlightMode !== "undefined") { WebInspector.domAgent.highlightDOMNode(self.node.id, self._highlightMode); } if (commitEditor) { self.dispatchEventToListeners("metrics edited"); self.update(); } }; var allProperties = this.inlineStyle.allProperties; for (var i = 0; i < allProperties.length; ++i) { var property = allProperties[i]; if (property.name !== context.styleProperty || property.inactive) continue; this.previousPropertyDataCandidate = property; property.setValue(userInput, commitEditor, true, callback); return; } this.inlineStyle.appendProperty(context.styleProperty, userInput, callback); }, editingCommitted: function(element, userInput, previousContent, context) { this.editingEnded(element, context); this._applyUserInput(element, userInput, previousContent, context, true); }, __proto__: WebInspector.SidebarPane.prototype } ; WebInspector.PropertiesSidebarPane = function() { WebInspector.SidebarPane.call(this, WebInspector.UIString("Properties")); } WebInspector.PropertiesSidebarPane._objectGroupName = "properties-sidebar-pane"; WebInspector.PropertiesSidebarPane.prototype = { update: function(node) { var body = this.bodyElement; if (!node) { body.removeChildren(); this.sections = []; return; } WebInspector.RemoteObject.resolveNode(node, WebInspector.PropertiesSidebarPane._objectGroupName, nodeResolved.bind(this)); function nodeResolved(object) { if (!object) return; function protoList() { var proto = this; var result = {}; var counter = 1; while (proto) { result[counter++] = proto; proto = proto.__proto__; } return result; } object.callFunction(protoList, undefined, nodePrototypesReady.bind(this)); object.release(); } function nodePrototypesReady(object) { if (!object) return; object.getOwnProperties(fillSection.bind(this)); } function fillSection(prototypes) { if (!prototypes) return; var body = this.bodyElement; body.removeChildren(); this.sections = []; for (var i = 0; i < prototypes.length; ++i) { if (!parseInt(prototypes[i].name, 10)) continue; var prototype = prototypes[i].value; var title = prototype.description; if (title.match(/Prototype$/)) title = title.replace(/Prototype$/, ""); var section = new WebInspector.ObjectPropertiesSection(prototype, title); this.sections.push(section); body.appendChild(section.element); } } }, __proto__: WebInspector.SidebarPane.prototype } ; WebInspector.StylesSidebarPane = function(computedStylePane, setPseudoClassCallback) { WebInspector.SidebarPane.call(this, WebInspector.UIString("Styles")); this.settingsSelectElement = document.createElement("select"); this.settingsSelectElement.className = "select-settings"; var option = document.createElement("option"); option.value = WebInspector.Color.Format.Original; option.label = WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "As authored" : "As Authored"); this.settingsSelectElement.appendChild(option); option = document.createElement("option"); option.value = WebInspector.Color.Format.HEX; option.label = WebInspector.UIString("Hex Colors"); this.settingsSelectElement.appendChild(option); option = document.createElement("option"); option.value = WebInspector.Color.Format.RGB; option.label = WebInspector.UIString("RGB Colors"); this.settingsSelectElement.appendChild(option); option = document.createElement("option"); option.value = WebInspector.Color.Format.HSL; option.label = WebInspector.UIString("HSL Colors"); this.settingsSelectElement.appendChild(option); var muteEventListener = function(event) { event.consume(true); }; this.settingsSelectElement.addEventListener("click", muteEventListener, true); this.settingsSelectElement.addEventListener("change", this._changeSetting.bind(this), false); this._updateColorFormatFilter(); this.titleElement.appendChild(this.settingsSelectElement); this._elementStateButton = document.createElement("button"); this._elementStateButton.className = "pane-title-button element-state"; this._elementStateButton.title = WebInspector.UIString("Toggle Element State"); this._elementStateButton.addEventListener("click", this._toggleElementStatePane.bind(this), false); this.titleElement.appendChild(this._elementStateButton); var addButton = document.createElement("button"); addButton.className = "pane-title-button add"; addButton.id = "add-style-button-test-id"; addButton.title = WebInspector.UIString("New Style Rule"); addButton.addEventListener("click", this._createNewRule.bind(this), false); this.titleElement.appendChild(addButton); this._computedStylePane = computedStylePane; computedStylePane._stylesSidebarPane = this; this._setPseudoClassCallback = setPseudoClassCallback; this.element.addEventListener("contextmenu", this._contextMenuEventFired.bind(this), true); WebInspector.settings.colorFormat.addChangeListener(this._colorFormatSettingChanged.bind(this)); this._createElementStatePane(); this.bodyElement.appendChild(this._elementStatePane); this._sectionsContainer = document.createElement("div"); this.bodyElement.appendChild(this._sectionsContainer); this._spectrumHelper = new WebInspector.SpectrumPopupHelper(); this._linkifier = new WebInspector.Linkifier(new WebInspector.Linkifier.DefaultCSSFormatter()); WebInspector.cssModel.addEventListener(WebInspector.CSSStyleModel.Events.StyleSheetChanged, this._styleSheetOrMediaQueryResultChanged, this); WebInspector.cssModel.addEventListener(WebInspector.CSSStyleModel.Events.MediaQueryResultChanged, this._styleSheetOrMediaQueryResultChanged, this); WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.AttrModified, this._attributeChanged, this); WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.AttrRemoved, this._attributeChanged, this); WebInspector.settings.showUserAgentStyles.addChangeListener(this._showUserAgentStylesSettingChanged.bind(this)); } WebInspector.StylesSidebarPane.PseudoIdNames = [ "", "first-line", "first-letter", "before", "after", "selection", "", "-webkit-scrollbar", "-webkit-file-upload-button", "-webkit-input-placeholder", "-webkit-slider-thumb", "-webkit-search-cancel-button", "-webkit-search-decoration", "-webkit-search-results-decoration", "-webkit-search-results-button", "-webkit-media-controls-panel", "-webkit-media-controls-play-button", "-webkit-media-controls-mute-button", "-webkit-media-controls-timeline", "-webkit-media-controls-timeline-container", "-webkit-media-controls-volume-slider", "-webkit-media-controls-volume-slider-container", "-webkit-media-controls-current-time-display", "-webkit-media-controls-time-remaining-display", "-webkit-media-controls-seek-back-button", "-webkit-media-controls-seek-forward-button", "-webkit-media-controls-fullscreen-button", "-webkit-media-controls-rewind-button", "-webkit-media-controls-return-to-realtime-button", "-webkit-media-controls-toggle-closed-captions-button", "-webkit-media-controls-status-display", "-webkit-scrollbar-thumb", "-webkit-scrollbar-button", "-webkit-scrollbar-track", "-webkit-scrollbar-track-piece", "-webkit-scrollbar-corner", "-webkit-resizer", "-webkit-inner-spin-button", "-webkit-outer-spin-button" ]; WebInspector.StylesSidebarPane.canonicalPropertyName = function(name) { if (!name || name.length < 9 || name.charAt(0) !== "-") return name; var match = name.match(/(?:-webkit-|-khtml-|-apple-)(.+)/); if (!match) return name; return match[1]; } WebInspector.StylesSidebarPane.createExclamationMark = function(propertyName) { var exclamationElement = document.createElement("img"); exclamationElement.className = "exclamation-mark"; exclamationElement.title = WebInspector.CSSCompletions.cssPropertiesMetainfo.keySet()[propertyName.toLowerCase()] ? WebInspector.UIString("Invalid property value.") : WebInspector.UIString("Unknown property name."); return exclamationElement; } WebInspector.StylesSidebarPane.prototype = { _contextMenuEventFired: function(event) { var contextMenu = new WebInspector.ContextMenu(event); contextMenu.appendApplicableItems(event.target); contextMenu.show(); }, get _forcedPseudoClasses() { return this.node ? (this.node.getUserProperty("pseudoState") || undefined) : undefined; }, _updateForcedPseudoStateInputs: function() { if (!this.node) return; var nodePseudoState = this._forcedPseudoClasses; if (!nodePseudoState) nodePseudoState = []; var inputs = this._elementStatePane.inputs; for (var i = 0; i < inputs.length; ++i) inputs[i].checked = nodePseudoState.indexOf(inputs[i].state) >= 0; }, update: function(node, forceUpdate) { this._spectrumHelper.hide(); var refresh = false; if (forceUpdate) delete this.node; if (!forceUpdate && (node === this.node)) refresh = true; if (node && node.nodeType() === Node.TEXT_NODE && node.parentNode) node = node.parentNode; if (node && node.nodeType() !== Node.ELEMENT_NODE) node = null; if (node) this.node = node; else node = this.node; this._updateForcedPseudoStateInputs(); if (refresh) this._refreshUpdate(); else this._rebuildUpdate(); }, _refreshUpdate: function(editedSection, forceFetchComputedStyle, userCallback) { if (this._refreshUpdateInProgress) { this._lastNodeForInnerRefresh = this.node; return; } var node = this._validateNode(userCallback); if (!node) return; function computedStyleCallback(computedStyle) { delete this._refreshUpdateInProgress; if (this._lastNodeForInnerRefresh) { delete this._lastNodeForInnerRefresh; this._refreshUpdate(editedSection, forceFetchComputedStyle, userCallback); return; } if (this.node === node && computedStyle) this._innerRefreshUpdate(node, computedStyle, editedSection); if (userCallback) userCallback(); } if (this._computedStylePane.expanded || forceFetchComputedStyle) { this._refreshUpdateInProgress = true; WebInspector.cssModel.getComputedStyleAsync(node.id, computedStyleCallback.bind(this)); } else { this._innerRefreshUpdate(node, null, editedSection); if (userCallback) userCallback(); } }, _rebuildUpdate: function() { if (this._rebuildUpdateInProgress) { this._lastNodeForInnerRebuild = this.node; return; } var node = this._validateNode(); if (!node) return; this._rebuildUpdateInProgress = true; var resultStyles = {}; function stylesCallback(matchedResult) { delete this._rebuildUpdateInProgress; var lastNodeForRebuild = this._lastNodeForInnerRebuild; if (lastNodeForRebuild) { delete this._lastNodeForInnerRebuild; if (lastNodeForRebuild !== this.node) { this._rebuildUpdate(); return; } } if (matchedResult && this.node === node) { resultStyles.matchedCSSRules = matchedResult.matchedCSSRules; resultStyles.pseudoElements = matchedResult.pseudoElements; resultStyles.inherited = matchedResult.inherited; this._innerRebuildUpdate(node, resultStyles); } if (lastNodeForRebuild) { this._rebuildUpdate(); return; } } function inlineCallback(inlineStyle, attributesStyle) { resultStyles.inlineStyle = inlineStyle; resultStyles.attributesStyle = attributesStyle; } function computedCallback(computedStyle) { resultStyles.computedStyle = computedStyle; } if (this._computedStylePane.expanded) WebInspector.cssModel.getComputedStyleAsync(node.id, computedCallback.bind(this)); WebInspector.cssModel.getInlineStylesAsync(node.id, inlineCallback.bind(this)); WebInspector.cssModel.getMatchedStylesAsync(node.id, true, true, stylesCallback.bind(this)); }, _validateNode: function(userCallback) { if (!this.node) { this._sectionsContainer.removeChildren(); this._computedStylePane.bodyElement.removeChildren(); this.sections = {}; if (userCallback) userCallback(); return null; } return this.node; }, _styleSheetOrMediaQueryResultChanged: function() { if (this._userOperation || this._isEditingStyle) return; this._rebuildUpdate(); }, _attributeChanged: function(event) { if (this._isEditingStyle || this._userOperation) return; if (!this._canAffectCurrentStyles(event.data.node)) return; this._rebuildUpdate(); }, _canAffectCurrentStyles: function(node) { return this.node && (this.node === node || node.parentNode === this.node.parentNode || node.isAncestor(this.node)); }, _innerRefreshUpdate: function(node, computedStyle, editedSection) { for (var pseudoId in this.sections) { var styleRules = this._refreshStyleRules(this.sections[pseudoId], computedStyle); var usedProperties = {}; this._markUsedProperties(styleRules, usedProperties); this._refreshSectionsForStyleRules(styleRules, usedProperties, editedSection); } if (computedStyle) this.sections[0][0].rebuildComputedTrace(this.sections[0]); this._nodeStylesUpdatedForTest(node, false); }, _innerRebuildUpdate: function(node, styles) { this._sectionsContainer.removeChildren(); this._computedStylePane.bodyElement.removeChildren(); this._linkifier.reset(); var styleRules = this._rebuildStyleRules(node, styles); var usedProperties = {}; this._markUsedProperties(styleRules, usedProperties); this.sections[0] = this._rebuildSectionsForStyleRules(styleRules, usedProperties, 0, null); var anchorElement = this.sections[0].inheritedPropertiesSeparatorElement; if (styles.computedStyle) this.sections[0][0].rebuildComputedTrace(this.sections[0]); for (var i = 0; i < styles.pseudoElements.length; ++i) { var pseudoElementCSSRules = styles.pseudoElements[i]; styleRules = []; var pseudoId = pseudoElementCSSRules.pseudoId; var entry = { isStyleSeparator: true, pseudoId: pseudoId }; styleRules.push(entry); for (var j = pseudoElementCSSRules.rules.length - 1; j >= 0; --j) { var rule = pseudoElementCSSRules.rules[j]; styleRules.push({ style: rule.style, selectorText: rule.selectorText, media: rule.media, sourceURL: rule.sourceURL, rule: rule, editable: !!(rule.style && rule.style.id) }); } usedProperties = {}; this._markUsedProperties(styleRules, usedProperties); this.sections[pseudoId] = this._rebuildSectionsForStyleRules(styleRules, usedProperties, pseudoId, anchorElement); } this._nodeStylesUpdatedForTest(node, true); }, _nodeStylesUpdatedForTest: function(node, rebuild) { }, _refreshStyleRules: function(sections, computedStyle) { var nodeComputedStyle = computedStyle; var styleRules = []; for (var i = 0; sections && i < sections.length; ++i) { var section = sections[i]; if (section.isBlank) continue; if (section.computedStyle) section.styleRule.style = nodeComputedStyle; var styleRule = { section: section, style: section.styleRule.style, computedStyle: section.computedStyle, rule: section.rule, editable: !!(section.styleRule.style && section.styleRule.style.id), isAttribute: section.styleRule.isAttribute, isInherited: section.styleRule.isInherited }; styleRules.push(styleRule); } return styleRules; }, _rebuildStyleRules: function(node, styles) { var nodeComputedStyle = styles.computedStyle; this.sections = {}; var styleRules = []; function addAttributesStyle() { if (!styles.attributesStyle) return; var attrStyle = { style: styles.attributesStyle, editable: false }; attrStyle.selectorText = node.nodeNameInCorrectCase() + "[" + WebInspector.UIString("Attributes Style") + "]"; styleRules.push(attrStyle); } styleRules.push({ computedStyle: true, selectorText: "", style: nodeComputedStyle, editable: false }); if (styles.inlineStyle && node.nodeType() === Node.ELEMENT_NODE) { var inlineStyle = { selectorText: "element.style", style: styles.inlineStyle, isAttribute: true }; styleRules.push(inlineStyle); } if (styles.matchedCSSRules.length) styleRules.push({ isStyleSeparator: true, text: WebInspector.UIString("Matched CSS Rules") }); var addedAttributesStyle; for (var i = styles.matchedCSSRules.length - 1; i >= 0; --i) { var rule = styles.matchedCSSRules[i]; if (!WebInspector.settings.showUserAgentStyles.get() && (rule.isUser || rule.isUserAgent)) continue; if ((rule.isUser || rule.isUserAgent) && !addedAttributesStyle) { addedAttributesStyle = true; addAttributesStyle(); } styleRules.push({ style: rule.style, selectorText: rule.selectorText, media: rule.media, sourceURL: rule.sourceURL, rule: rule, editable: !!(rule.style && rule.style.id) }); } if (!addedAttributesStyle) addAttributesStyle(); var parentNode = node.parentNode; function insertInheritedNodeSeparator(node) { var entry = {}; entry.isStyleSeparator = true; entry.node = node; styleRules.push(entry); } for (var parentOrdinal = 0; parentOrdinal < styles.inherited.length; ++parentOrdinal) { var parentStyles = styles.inherited[parentOrdinal]; var separatorInserted = false; if (parentStyles.inlineStyle) { if (this._containsInherited(parentStyles.inlineStyle)) { var inlineStyle = { selectorText: WebInspector.UIString("Style Attribute"), style: parentStyles.inlineStyle, isAttribute: true, isInherited: true, parentNode: parentNode }; if (!separatorInserted) { insertInheritedNodeSeparator(parentNode); separatorInserted = true; } styleRules.push(inlineStyle); } } for (var i = parentStyles.matchedCSSRules.length - 1; i >= 0; --i) { var rulePayload = parentStyles.matchedCSSRules[i]; if (!this._containsInherited(rulePayload.style)) continue; var rule = rulePayload; if (!WebInspector.settings.showUserAgentStyles.get() && (rule.isUser || rule.isUserAgent)) continue; if (!separatorInserted) { insertInheritedNodeSeparator(parentNode); separatorInserted = true; } styleRules.push({ style: rule.style, selectorText: rule.selectorText, media: rule.media, sourceURL: rule.sourceURL, rule: rule, isInherited: true, parentNode: parentNode, editable: !!(rule.style && rule.style.id) }); } parentNode = parentNode.parentNode; } return styleRules; }, _markUsedProperties: function(styleRules, usedProperties) { var foundImportantProperties = {}; var propertyToEffectiveRule = {}; for (var i = 0; i < styleRules.length; ++i) { var styleRule = styleRules[i]; if (styleRule.computedStyle || styleRule.isStyleSeparator) continue; if (styleRule.section && styleRule.section.noAffect) continue; styleRule.usedProperties = {}; var style = styleRule.style; var allProperties = style.allProperties; for (var j = 0; j < allProperties.length; ++j) { var property = allProperties[j]; if (!property.isLive || !property.parsedOk) continue; var canonicalName = WebInspector.StylesSidebarPane.canonicalPropertyName(property.name); if (styleRule.isInherited && !WebInspector.CSSKeywordCompletions.InheritedProperties[canonicalName]) continue; if (foundImportantProperties.hasOwnProperty(canonicalName)) continue; var isImportant = property.priority.length; if (!isImportant && usedProperties.hasOwnProperty(canonicalName)) continue; if (isImportant) { foundImportantProperties[canonicalName] = true; if (propertyToEffectiveRule.hasOwnProperty(canonicalName)) delete propertyToEffectiveRule[canonicalName].usedProperties[canonicalName]; } styleRule.usedProperties[canonicalName] = true; usedProperties[canonicalName] = true; propertyToEffectiveRule[canonicalName] = styleRule; } } }, _refreshSectionsForStyleRules: function(styleRules, usedProperties, editedSection) { for (var i = 0; i < styleRules.length; ++i) { var styleRule = styleRules[i]; var section = styleRule.section; if (styleRule.computedStyle) { section._usedProperties = usedProperties; section.update(); } else { section._usedProperties = styleRule.usedProperties; section.update(section === editedSection); } } }, _rebuildSectionsForStyleRules: function(styleRules, usedProperties, pseudoId, anchorElement) { var sections = []; var lastWasSeparator = true; for (var i = 0; i < styleRules.length; ++i) { var styleRule = styleRules[i]; if (styleRule.isStyleSeparator) { var separatorElement = document.createElement("div"); separatorElement.className = "sidebar-separator"; if (styleRule.node) { var link = WebInspector.DOMPresentationUtils.linkifyNodeReference(styleRule.node); separatorElement.appendChild(document.createTextNode(WebInspector.UIString("Inherited from") + " ")); separatorElement.appendChild(link); if (!sections.inheritedPropertiesSeparatorElement) sections.inheritedPropertiesSeparatorElement = separatorElement; } else if ("pseudoId" in styleRule) { var pseudoName = WebInspector.StylesSidebarPane.PseudoIdNames[styleRule.pseudoId]; if (pseudoName) separatorElement.textContent = WebInspector.UIString("Pseudo ::%s element", pseudoName); else separatorElement.textContent = WebInspector.UIString("Pseudo element"); } else separatorElement.textContent = styleRule.text; this._sectionsContainer.insertBefore(separatorElement, anchorElement); lastWasSeparator = true; continue; } var computedStyle = styleRule.computedStyle; var editable = styleRule.editable; if (typeof editable === "undefined") editable = true; if (computedStyle) var section = new WebInspector.ComputedStylePropertiesSection(this, styleRule, usedProperties); else { var section = new WebInspector.StylePropertiesSection(this, styleRule, editable, styleRule.isInherited, lastWasSeparator); section._markSelectorMatches(); } section.expanded = true; if (computedStyle) { this._computedStylePane.bodyElement.appendChild(section.element); lastWasSeparator = true; } else { this._sectionsContainer.insertBefore(section.element, anchorElement); lastWasSeparator = false; } sections.push(section); } return sections; }, _containsInherited: function(style) { var properties = style.allProperties; for (var i = 0; i < properties.length; ++i) { var property = properties[i]; if (property.isLive && property.name in WebInspector.CSSKeywordCompletions.InheritedProperties) return true; } return false; }, _colorFormatSettingChanged: function(event) { this._updateColorFormatFilter(); for (var pseudoId in this.sections) { var sections = this.sections[pseudoId]; for (var i = 0; i < sections.length; ++i) sections[i].update(true); } }, _updateColorFormatFilter: function() { var selectedIndex = 0; var value = WebInspector.settings.colorFormat.get(); var options = this.settingsSelectElement.options; for (var i = 0; i < options.length; ++i) { if (options[i].value === value) { selectedIndex = i; break; } } this.settingsSelectElement.selectedIndex = selectedIndex; }, _changeSetting: function(event) { var options = this.settingsSelectElement.options; var selectedOption = options[this.settingsSelectElement.selectedIndex]; WebInspector.settings.colorFormat.set(selectedOption.value); }, _createNewRule: function(event) { event.consume(); this.expanded = true; this.addBlankSection().startEditingSelector(); }, addBlankSection: function() { var blankSection = new WebInspector.BlankStylePropertiesSection(this, this.node ? this.node.appropriateSelectorFor(true) : ""); var elementStyleSection = this.sections[0][1]; this._sectionsContainer.insertBefore(blankSection.element, elementStyleSection.element.nextSibling); this.sections[0].splice(2, 0, blankSection); return blankSection; }, removeSection: function(section) { for (var pseudoId in this.sections) { var sections = this.sections[pseudoId]; var index = sections.indexOf(section); if (index === -1) continue; sections.splice(index, 1); if (section.element.parentNode) section.element.parentNode.removeChild(section.element); } }, registerShortcuts: function() { var section = WebInspector.shortcutsScreen.section(WebInspector.UIString("Styles Pane")); var shortcut = WebInspector.KeyboardShortcut; var keys = [ shortcut.shortcutToString(shortcut.Keys.Tab), shortcut.shortcutToString(shortcut.Keys.Tab, shortcut.Modifiers.Shift) ]; section.addRelatedKeys(keys, WebInspector.UIString("Next/previous property")); keys = [ shortcut.shortcutToString(shortcut.Keys.Up), shortcut.shortcutToString(shortcut.Keys.Down) ]; section.addRelatedKeys(keys, WebInspector.UIString("Increment/decrement value")); keys = [ shortcut.shortcutToString(shortcut.Keys.Up, shortcut.Modifiers.Shift), shortcut.shortcutToString(shortcut.Keys.Down, shortcut.Modifiers.Shift) ]; section.addRelatedKeys(keys, WebInspector.UIString("Increment/decrement by %f", 10)); keys = [ shortcut.shortcutToString(shortcut.Keys.PageUp), shortcut.shortcutToString(shortcut.Keys.PageDown) ]; section.addRelatedKeys(keys, WebInspector.UIString("Increment/decrement by %f", 10)); keys = [ shortcut.shortcutToString(shortcut.Keys.PageUp, shortcut.Modifiers.Shift), shortcut.shortcutToString(shortcut.Keys.PageDown, shortcut.Modifiers.Shift) ]; section.addRelatedKeys(keys, WebInspector.UIString("Increment/decrement by %f", 100)); keys = [ shortcut.shortcutToString(shortcut.Keys.PageUp, shortcut.Modifiers.Alt), shortcut.shortcutToString(shortcut.Keys.PageDown, shortcut.Modifiers.Alt) ]; section.addRelatedKeys(keys, WebInspector.UIString("Increment/decrement by %f", 0.1)); }, _toggleElementStatePane: function(event) { event.consume(); if (!this._elementStateButton.hasStyleClass("toggled")) { this.expand(); this._elementStateButton.addStyleClass("toggled"); this._elementStatePane.addStyleClass("expanded"); } else { this._elementStateButton.removeStyleClass("toggled"); this._elementStatePane.removeStyleClass("expanded"); } }, _createElementStatePane: function() { this._elementStatePane = document.createElement("div"); this._elementStatePane.className = "styles-element-state-pane source-code"; var table = document.createElement("table"); var inputs = []; this._elementStatePane.inputs = inputs; function clickListener(event) { var node = this._validateNode(); if (!node) return; this._setPseudoClassCallback(node.id, event.target.state, event.target.checked); } function createCheckbox(state) { var td = document.createElement("td"); var label = document.createElement("label"); var input = document.createElement("input"); input.type = "checkbox"; input.state = state; input.addEventListener("click", clickListener.bind(this), false); inputs.push(input); label.appendChild(input); label.appendChild(document.createTextNode(":" + state)); td.appendChild(label); return td; } var tr = document.createElement("tr"); tr.appendChild(createCheckbox.call(this, "active")); tr.appendChild(createCheckbox.call(this, "hover")); table.appendChild(tr); tr = document.createElement("tr"); tr.appendChild(createCheckbox.call(this, "focus")); tr.appendChild(createCheckbox.call(this, "visited")); table.appendChild(tr); this._elementStatePane.appendChild(table); }, _showUserAgentStylesSettingChanged: function() { this._rebuildUpdate(); }, willHide: function() { this._spectrumHelper.hide(); }, __proto__: WebInspector.SidebarPane.prototype } WebInspector.ComputedStyleSidebarPane = function() { WebInspector.SidebarPane.call(this, WebInspector.UIString("Computed Style")); var showInheritedCheckbox = new WebInspector.Checkbox(WebInspector.UIString("Show inherited"), "sidebar-pane-subtitle"); this.titleElement.appendChild(showInheritedCheckbox.element); if (WebInspector.settings.showInheritedComputedStyleProperties.get()) { this.bodyElement.addStyleClass("show-inherited"); showInheritedCheckbox.checked = true; } function showInheritedToggleFunction(event) { WebInspector.settings.showInheritedComputedStyleProperties.set(showInheritedCheckbox.checked); if (WebInspector.settings.showInheritedComputedStyleProperties.get()) this.bodyElement.addStyleClass("show-inherited"); else this.bodyElement.removeStyleClass("show-inherited"); } showInheritedCheckbox.addEventListener(showInheritedToggleFunction.bind(this)); } WebInspector.ComputedStyleSidebarPane.prototype = { expand: function() { function callback() { WebInspector.SidebarPane.prototype.expand.call(this); } this._stylesSidebarPane._refreshUpdate(null, true, callback.bind(this)); }, __proto__: WebInspector.SidebarPane.prototype } WebInspector.StylePropertiesSection = function(parentPane, styleRule, editable, isInherited, isFirstSection) { WebInspector.PropertiesSection.call(this, ""); this.element.className = "styles-section matched-styles monospace" + (isFirstSection ? " first-styles-section" : ""); if (styleRule.media) { for (var i = styleRule.media.length - 1; i >= 0; --i) { var media = styleRule.media[i]; var mediaDataElement = this.titleElement.createChild("div", "media"); var mediaText; switch (media.source) { case WebInspector.CSSMedia.Source.LINKED_SHEET: case WebInspector.CSSMedia.Source.INLINE_SHEET: mediaText = "media=\"" + media.text + "\""; break; case WebInspector.CSSMedia.Source.MEDIA_RULE: mediaText = "@media " + media.text; break; case WebInspector.CSSMedia.Source.IMPORT_RULE: mediaText = "@import " + media.text; break; } if (media.sourceURL) { var refElement = mediaDataElement.createChild("div", "subtitle"); var lineNumber = media.sourceLine < 0 ? undefined : media.sourceLine; var anchor = WebInspector.linkifyResourceAsNode(media.sourceURL, lineNumber, "subtitle", media.sourceURL + (isNaN(lineNumber) ? "" : (":" + (lineNumber + 1)))); anchor.preferredPanel = "scripts"; anchor.style.float = "right"; refElement.appendChild(anchor); } var mediaTextElement = mediaDataElement.createChild("span"); mediaTextElement.textContent = mediaText; mediaTextElement.title = media.text; } } var selectorContainer = document.createElement("div"); this._selectorElement = document.createElement("span"); this._selectorElement.addStyleClass("selector-matches"); this._selectorElement.textContent = styleRule.selectorText; selectorContainer.appendChild(this._selectorElement); var openBrace = document.createElement("span"); openBrace.textContent = " {"; selectorContainer.appendChild(openBrace); selectorContainer.addEventListener("mousedown", this._handleEmptySpaceMouseDown.bind(this), false); selectorContainer.addEventListener("click", this._handleSelectorContainerClick.bind(this), false); var closeBrace = document.createElement("div"); closeBrace.textContent = "}"; this.element.appendChild(closeBrace); this._selectorElement.addEventListener("click", this._handleSelectorClick.bind(this), false); this.element.addEventListener("mousedown", this._handleEmptySpaceMouseDown.bind(this), false); this.element.addEventListener("click", this._handleEmptySpaceClick.bind(this), false); this._parentPane = parentPane; this.styleRule = styleRule; this.rule = this.styleRule.rule; this.editable = editable; this.isInherited = isInherited; if (this.rule) { if (this.rule.isUserAgent || this.rule.isUser) this.editable = false; this.titleElement.addStyleClass("styles-selector"); } this._usedProperties = styleRule.usedProperties; this._selectorRefElement = document.createElement("div"); this._selectorRefElement.className = "subtitle"; this._selectorRefElement.appendChild(this._createRuleOriginNode()); selectorContainer.insertBefore(this._selectorRefElement, selectorContainer.firstChild); this.titleElement.appendChild(selectorContainer); this._selectorContainer = selectorContainer; if (isInherited) this.element.addStyleClass("show-inherited"); if (!this.editable) this.element.addStyleClass("read-only"); } WebInspector.StylePropertiesSection.prototype = { get pane() { return this._parentPane; }, collapse: function(dontRememberState) { }, isPropertyInherited: function(propertyName) { if (this.isInherited) { return !(propertyName in WebInspector.CSSKeywordCompletions.InheritedProperties); } return false; }, isPropertyOverloaded: function(propertyName, isShorthand) { if (!this._usedProperties || this.noAffect) return false; if (this.isInherited && !(propertyName in WebInspector.CSSKeywordCompletions.InheritedProperties)) { return false; } var canonicalName = WebInspector.StylesSidebarPane.canonicalPropertyName(propertyName); var used = (canonicalName in this._usedProperties); if (used || !isShorthand) return !used; var longhandProperties = this.styleRule.style.longhandProperties(propertyName); for (var j = 0; j < longhandProperties.length; ++j) { var individualProperty = longhandProperties[j]; if (WebInspector.StylesSidebarPane.canonicalPropertyName(individualProperty.name) in this._usedProperties) return false; } return true; }, nextEditableSibling: function() { var curSection = this; do { curSection = curSection.nextSibling; } while (curSection && !curSection.editable); if (!curSection) { curSection = this.firstSibling; while (curSection && !curSection.editable) curSection = curSection.nextSibling; } return (curSection && curSection.editable) ? curSection : null; }, previousEditableSibling: function() { var curSection = this; do { curSection = curSection.previousSibling; } while (curSection && !curSection.editable); if (!curSection) { curSection = this.lastSibling; while (curSection && !curSection.editable) curSection = curSection.previousSibling; } return (curSection && curSection.editable) ? curSection : null; }, update: function(full) { if (full) { this.propertiesTreeOutline.removeChildren(); this.populated = false; } else { var child = this.propertiesTreeOutline.children[0]; while (child) { child.overloaded = this.isPropertyOverloaded(child.name, child.isShorthand); child = child.traverseNextTreeElement(false, null, true); } } this.afterUpdate(); }, afterUpdate: function() { if (this._afterUpdate) { this._afterUpdate(this); delete this._afterUpdate; } }, onpopulate: function() { var style = this.styleRule.style; var allProperties = style.allProperties; this.uniqueProperties = []; var styleHasEditableSource = this.editable && !!style.range; if (styleHasEditableSource) { for (var i = 0; i < allProperties.length; ++i) { var property = allProperties[i]; this.uniqueProperties.push(property); if (property.styleBased) continue; var isShorthand = !!WebInspector.CSSCompletions.cssPropertiesMetainfo.longhands(property.name); var inherited = this.isPropertyInherited(property.name); var overloaded = property.inactive || this.isPropertyOverloaded(property.name); var item = new WebInspector.StylePropertyTreeElement(this, this._parentPane, this.styleRule, style, property, isShorthand, inherited, overloaded); this.propertiesTreeOutline.appendChild(item); } return; } var generatedShorthands = {}; for (var i = 0; i < allProperties.length; ++i) { var property = allProperties[i]; this.uniqueProperties.push(property); var isShorthand = !!WebInspector.CSSCompletions.cssPropertiesMetainfo.longhands(property.name); var shorthands = isShorthand ? null : WebInspector.CSSCompletions.cssPropertiesMetainfo.shorthands(property.name); var shorthandPropertyAvailable = false; for (var j = 0; shorthands && !shorthandPropertyAvailable && j < shorthands.length; ++j) { var shorthand = shorthands[j]; if (shorthand in generatedShorthands) { shorthandPropertyAvailable = true; continue; } if (style.getLiveProperty(shorthand)) { shorthandPropertyAvailable = true; continue; } if (!style.shorthandValue(shorthand)) { shorthandPropertyAvailable = false; continue; } var shorthandProperty = new WebInspector.CSSProperty(style, style.allProperties.length, shorthand, style.shorthandValue(shorthand), "", "style", true, true, undefined); var overloaded = property.inactive || this.isPropertyOverloaded(property.name, true); var item = new WebInspector.StylePropertyTreeElement(this, this._parentPane, this.styleRule, style, shorthandProperty, true, false, overloaded); this.propertiesTreeOutline.appendChild(item); generatedShorthands[shorthand] = shorthandProperty; shorthandPropertyAvailable = true; } if (shorthandPropertyAvailable) continue; var inherited = this.isPropertyInherited(property.name); var overloaded = property.inactive || this.isPropertyOverloaded(property.name, isShorthand); var item = new WebInspector.StylePropertyTreeElement(this, this._parentPane, this.styleRule, style, property, isShorthand, inherited, overloaded); this.propertiesTreeOutline.appendChild(item); } }, findTreeElementWithName: function(name) { var treeElement = this.propertiesTreeOutline.children[0]; while (treeElement) { if (treeElement.name === name) return treeElement; treeElement = treeElement.traverseNextTreeElement(true, null, true); } return null; }, _markSelectorMatches: function() { var rule = this.styleRule.rule; if (!rule) return; var selectors = rule.selectors; var matchingSelectors = rule.matchingSelectors; if (selectors.length < 2 || !matchingSelectors) return; var fragment = document.createDocumentFragment(); var currentMatch = 0; for (var i = 0, lastSelectorIndex = selectors.length - 1; i <= lastSelectorIndex ; ++i) { var selectorNode; var textNode = document.createTextNode(selectors[i]); if (matchingSelectors[currentMatch] === i) { ++currentMatch; selectorNode = document.createElement("span"); selectorNode.className = "selector-matches"; selectorNode.appendChild(textNode); } else selectorNode = textNode; fragment.appendChild(selectorNode); if (i !== lastSelectorIndex) fragment.appendChild(document.createTextNode(", ")); } this._selectorElement.className = "selector"; this._selectorElement.removeChildren(); this._selectorElement.appendChild(fragment); }, _checkWillCancelEditing: function() { var willCauseCancelEditing = this._willCauseCancelEditing; delete this._willCauseCancelEditing; return willCauseCancelEditing; }, _handleSelectorContainerClick: function(event) { if (this._checkWillCancelEditing() || !this.editable) return; if (event.target === this._selectorContainer) this.addNewBlankProperty(0).startEditing(); }, addNewBlankProperty: function(index) { var style = this.styleRule.style; var property = style.newBlankProperty(index); var item = new WebInspector.StylePropertyTreeElement(this, this._parentPane, this.styleRule, style, property, false, false, false); index = property.index; this.propertiesTreeOutline.insertChild(item, index); item.listItemElement.textContent = ""; item._newProperty = true; item.updateTitle(); return item; }, _createRuleOriginNode: function() { function linkifyUncopyable(url, line) { var link = WebInspector.linkifyResourceAsNode(url, line, "", url + ":" + (line + 1)); link.preferredPanel = "scripts"; link.classList.add("webkit-html-resource-link"); link.setAttribute("data-uncopyable", link.textContent); link.textContent = ""; return link; } if (this.styleRule.sourceURL) return this._parentPane._linkifier.linkifyCSSRuleLocation(this.rule) || linkifyUncopyable(this.styleRule.sourceURL, this.rule.sourceLine); if (!this.rule) return document.createTextNode(""); var origin = ""; if (this.rule.isUserAgent) return document.createTextNode(WebInspector.UIString("user agent stylesheet")); if (this.rule.isUser) return document.createTextNode(WebInspector.UIString("user stylesheet")); if (this.rule.isViaInspector) { var element = document.createElement("span"); function callback(resource) { if (resource) element.appendChild(linkifyUncopyable(resource.url, this.rule.sourceLine)); else element.textContent = WebInspector.UIString("via inspector"); } WebInspector.cssModel.getViaInspectorResourceForRule(this.rule, callback.bind(this)); return element; } }, _handleEmptySpaceMouseDown: function(event) { this._willCauseCancelEditing = this._parentPane._isEditingStyle; }, _handleEmptySpaceClick: function(event) { if (!this.editable) return; if (!window.getSelection().isCollapsed) return; if (this._checkWillCancelEditing()) return; if (event.target.hasStyleClass("header") || this.element.hasStyleClass("read-only") || event.target.enclosingNodeOrSelfWithClass("media")) { event.consume(); return; } this.expand(); this.addNewBlankProperty().startEditing(); }, _handleSelectorClick: function(event) { this._startEditingOnMouseEvent(); event.consume(true); }, _startEditingOnMouseEvent: function() { if (!this.editable) return; if (!this.rule && this.propertiesTreeOutline.children.length === 0) { this.expand(); this.addNewBlankProperty().startEditing(); return; } if (!this.rule) return; this.startEditingSelector(); }, startEditingSelector: function() { var element = this._selectorElement; if (WebInspector.isBeingEdited(element)) return; element.scrollIntoViewIfNeeded(false); element.textContent = element.textContent; var config = new WebInspector.EditingConfig(this.editingSelectorCommitted.bind(this), this.editingSelectorCancelled.bind(this)); WebInspector.startEditing(this._selectorElement, config); window.getSelection().setBaseAndExtent(element, 0, element, 1); }, _moveEditorFromSelector: function(moveDirection) { this._markSelectorMatches(); if (!moveDirection) return; if (moveDirection === "forward") { this.expand(); var firstChild = this.propertiesTreeOutline.children[0]; while (firstChild && firstChild.inherited) firstChild = firstChild.nextSibling; if (!firstChild) this.addNewBlankProperty().startEditing(); else firstChild.startEditing(firstChild.nameElement); } else { var previousSection = this.previousEditableSibling(); if (!previousSection) return; previousSection.expand(); previousSection.addNewBlankProperty().startEditing(); } }, editingSelectorCommitted: function(element, newContent, oldContent, context, moveDirection) { if (newContent) newContent = newContent.trim(); if (newContent === oldContent) { this._selectorElement.textContent = newContent; return this._moveEditorFromSelector(moveDirection); } function successCallback(newRule, doesAffectSelectedNode) { if (!doesAffectSelectedNode) { this.noAffect = true; this.element.addStyleClass("no-affect"); } else { delete this.noAffect; this.element.removeStyleClass("no-affect"); } this.rule = newRule; this.styleRule = { section: this, style: newRule.style, selectorText: newRule.selectorText, media: newRule.media, sourceURL: newRule.sourceURL, rule: newRule }; this._parentPane.update(); this._moveEditorFromSelector(moveDirection); } var selectedNode = this._parentPane.node; WebInspector.cssModel.setRuleSelector(this.rule.id, selectedNode ? selectedNode.id : 0, newContent, successCallback.bind(this), this._moveEditorFromSelector.bind(this, moveDirection)); }, editingSelectorCancelled: function() { this._markSelectorMatches(); }, __proto__: WebInspector.PropertiesSection.prototype } WebInspector.ComputedStylePropertiesSection = function(parentPane, styleRule, usedProperties) { WebInspector.PropertiesSection.call(this, ""); this.headerElement.addStyleClass("hidden"); this.element.className = "styles-section monospace first-styles-section read-only computed-style"; this._parentPane = parentPane; this.styleRule = styleRule; this._usedProperties = usedProperties; this._alwaysShowComputedProperties = { "display": true, "height": true, "width": true }; this.computedStyle = true; this._propertyTreeElements = {}; this._expandedPropertyNames = {}; } WebInspector.ComputedStylePropertiesSection.prototype = { get pane() { return this._parentPane; }, collapse: function(dontRememberState) { }, _isPropertyInherited: function(propertyName) { var canonicalName = WebInspector.StylesSidebarPane.canonicalPropertyName(propertyName); return !(canonicalName in this._usedProperties) && !(canonicalName in this._alwaysShowComputedProperties); }, update: function() { this._expandedPropertyNames = {}; for (var name in this._propertyTreeElements) { if (this._propertyTreeElements[name].expanded) this._expandedPropertyNames[name] = true; } this._propertyTreeElements = {}; this.propertiesTreeOutline.removeChildren(); this.populated = false; }, onpopulate: function() { function sorter(a, b) { return a.name.localeCompare(b.name); } var style = this.styleRule.style; if (!style) return; var uniqueProperties = []; var allProperties = style.allProperties; for (var i = 0; i < allProperties.length; ++i) uniqueProperties.push(allProperties[i]); uniqueProperties.sort(sorter); this._propertyTreeElements = {}; for (var i = 0; i < uniqueProperties.length; ++i) { var property = uniqueProperties[i]; var inherited = this._isPropertyInherited(property.name); var item = new WebInspector.StylePropertyTreeElement(this, this._parentPane, this.styleRule, style, property, false, inherited, false); this.propertiesTreeOutline.appendChild(item); this._propertyTreeElements[property.name] = item; } }, rebuildComputedTrace: function(sections) { for (var i = 0; i < sections.length; ++i) { var section = sections[i]; if (section.computedStyle || section.isBlank) continue; for (var j = 0; j < section.uniqueProperties.length; ++j) { var property = section.uniqueProperties[j]; if (property.disabled) continue; if (section.isInherited && !(property.name in WebInspector.CSSKeywordCompletions.InheritedProperties)) continue; var treeElement = this._propertyTreeElements[property.name]; if (treeElement) { var fragment = document.createDocumentFragment(); var selector = fragment.createChild("span"); selector.style.color = "gray"; selector.textContent = section.styleRule.selectorText; fragment.appendChild(document.createTextNode(" - " + property.value + " ")); var subtitle = fragment.createChild("span"); subtitle.style.float = "right"; subtitle.appendChild(section._createRuleOriginNode()); var childElement = new TreeElement(fragment, null, false); treeElement.appendChild(childElement); if (property.inactive || section.isPropertyOverloaded(property.name)) childElement.listItemElement.addStyleClass("overloaded"); if (!property.parsedOk) { childElement.listItemElement.addStyleClass("not-parsed-ok"); childElement.listItemElement.insertBefore(WebInspector.StylesSidebarPane.createExclamationMark(property.name), childElement.listItemElement.firstChild); } } } } for (var name in this._expandedPropertyNames) { if (name in this._propertyTreeElements) this._propertyTreeElements[name].expand(); } }, __proto__: WebInspector.PropertiesSection.prototype } WebInspector.BlankStylePropertiesSection = function(parentPane, defaultSelectorText) { WebInspector.StylePropertiesSection.call(this, parentPane, {selectorText: defaultSelectorText, rule: {isViaInspector: true}}, true, false, false); this.element.addStyleClass("blank-section"); } WebInspector.BlankStylePropertiesSection.prototype = { get isBlank() { return !this._normal; }, expand: function() { if (!this.isBlank) WebInspector.StylePropertiesSection.prototype.expand.call(this); }, editingSelectorCommitted: function(element, newContent, oldContent, context, moveDirection) { if (!this.isBlank) { WebInspector.StylePropertiesSection.prototype.editingSelectorCommitted.call(this, element, newContent, oldContent, context, moveDirection); return; } function successCallback(newRule, doesSelectorAffectSelectedNode) { var styleRule = { section: this, style: newRule.style, selectorText: newRule.selectorText, sourceURL: newRule.sourceURL, rule: newRule }; this.makeNormal(styleRule); if (!doesSelectorAffectSelectedNode) { this.noAffect = true; this.element.addStyleClass("no-affect"); } this._selectorRefElement.removeChildren(); this._selectorRefElement.appendChild(this._createRuleOriginNode()); this.expand(); if (this.element.parentElement) this._moveEditorFromSelector(moveDirection); delete this._parentPane._userOperation; } this._parentPane._userOperation = true; WebInspector.cssModel.addRule(this.pane.node.id, newContent, successCallback.bind(this), this.editingSelectorCancelled.bind(this)); }, editingSelectorCancelled: function() { if (!this.isBlank) { WebInspector.StylePropertiesSection.prototype.editingSelectorCancelled.call(this); return; } this.pane.removeSection(this); }, makeNormal: function(styleRule) { this.element.removeStyleClass("blank-section"); this.styleRule = styleRule; this.rule = styleRule.rule; this._normal = true; }, __proto__: WebInspector.StylePropertiesSection.prototype } WebInspector.StylePropertyTreeElement = function(section, parentPane, styleRule, style, property, isShorthand, inherited, overloaded) { this.section = section; this._parentPane = parentPane; this._styleRule = styleRule; this.style = style; this.property = property; this.isShorthand = isShorthand; this._inherited = inherited; this._overloaded = overloaded; TreeElement.call(this, "", null, isShorthand); this.selectable = false; } WebInspector.StylePropertyTreeElement.prototype = { get inherited() { return this._inherited; }, set inherited(x) { if (x === this._inherited) return; this._inherited = x; this.updateState(); }, get overloaded() { return this._overloaded; }, set overloaded(x) { if (x === this._overloaded) return; this._overloaded = x; this.updateState(); }, get disabled() { return this.property.disabled; }, get name() { if (!this.disabled || !this.property.text) return this.property.name; var text = this.property.text; var index = text.indexOf(":"); if (index < 1) return this.property.name; return text.substring(0, index).trim(); }, get priority() { if (this.disabled) return ""; return this.property.priority; }, get value() { if (!this.disabled || !this.property.text) return this.property.value; var match = this.property.text.match(/(.*);\s*/); if (!match || !match[1]) return this.property.value; var text = match[1]; var index = text.indexOf(":"); if (index < 1) return this.property.value; return text.substring(index + 1).trim(); }, get parsedOk() { return this.property.parsedOk; }, onattach: function() { this.updateTitle(); this.listItemElement.addEventListener("mousedown", this._mouseDown.bind(this)); this.listItemElement.addEventListener("mouseup", this._resetMouseDownElement.bind(this)); this.listItemElement.addEventListener("click", this._mouseClick.bind(this)); }, _mouseDown: function(event) { if (this._parentPane) { this._parentPane._mouseDownTreeElement = this; this._parentPane._mouseDownTreeElementIsName = this._isNameElement(event.target); this._parentPane._mouseDownTreeElementIsValue = this._isValueElement(event.target); } }, _resetMouseDownElement: function() { if (this._parentPane) { delete this._parentPane._mouseDownTreeElement; delete this._parentPane._mouseDownTreeElementIsName; delete this._parentPane._mouseDownTreeElementIsValue; } }, updateTitle: function() { var value = this.value; this.updateState(); var enabledCheckboxElement; if (this.parsedOk) { enabledCheckboxElement = document.createElement("input"); enabledCheckboxElement.className = "enabled-button"; enabledCheckboxElement.type = "checkbox"; enabledCheckboxElement.checked = !this.disabled; enabledCheckboxElement.addEventListener("click", this.toggleEnabled.bind(this), false); } var nameElement = document.createElement("span"); nameElement.className = "webkit-css-property"; nameElement.textContent = this.name; nameElement.title = this.property.propertyText; this.nameElement = nameElement; this._expandElement = document.createElement("span"); this._expandElement.className = "expand-element"; var valueElement = document.createElement("span"); valueElement.className = "value"; this.valueElement = valueElement; var cf = WebInspector.Color.Format; if (value) { var self = this; function processValue(regex, processor, nextProcessor, valueText) { var container = document.createDocumentFragment(); var items = valueText.replace(regex, "\0$1\0").split("\0"); for (var i = 0; i < items.length; ++i) { if ((i % 2) === 0) { if (nextProcessor) container.appendChild(nextProcessor(items[i])); else container.appendChild(document.createTextNode(items[i])); } else { var processedNode = processor(items[i]); if (processedNode) container.appendChild(processedNode); } } return container; } function linkifyURL(url) { var hrefUrl = url; var match = hrefUrl.match(/['"]?([^'"]+)/); if (match) hrefUrl = match[1]; var container = document.createDocumentFragment(); container.appendChild(document.createTextNode("url(")); if (self._styleRule.sourceURL) hrefUrl = WebInspector.ParsedURL.completeURL(self._styleRule.sourceURL, hrefUrl); else if (self._parentPane.node) hrefUrl = self._parentPane.node.resolveURL(hrefUrl); var hasResource = !!WebInspector.resourceForURL(hrefUrl); container.appendChild(WebInspector.linkifyURLAsNode(hrefUrl, url, undefined, !hasResource)); container.appendChild(document.createTextNode(")")); return container; } function processColor(text) { try { var color = new WebInspector.Color(text); } catch (e) { return document.createTextNode(text); } var format = getFormat(); var hasSpectrum = self._parentPane; var spectrumHelper = hasSpectrum ? self._parentPane._spectrumHelper : null; var spectrum = spectrumHelper ? spectrumHelper.spectrum() : null; var colorSwatch = new WebInspector.ColorSwatch(); colorSwatch.setColorString(text); colorSwatch.element.addEventListener("click", swatchClick, false); var scrollerElement = hasSpectrum ? self._parentPane._computedStylePane.element.parentElement : null; function spectrumChanged(e) { color = e.data; var colorString = color.toString(); colorValueElement.textContent = colorString; colorSwatch.setColorString(colorString); self.applyStyleText(nameElement.textContent + ": " + valueElement.textContent, false, false, false); } function spectrumHidden(event) { scrollerElement.removeEventListener("scroll", repositionSpectrum, false); var commitEdit = event.data; var propertyText = !commitEdit && self.originalPropertyText ? self.originalPropertyText : (nameElement.textContent + ": " + valueElement.textContent); self.applyStyleText(propertyText, true, true, false); spectrum.removeEventListener(WebInspector.Spectrum.Events.ColorChanged, spectrumChanged); spectrumHelper.removeEventListener(WebInspector.SpectrumPopupHelper.Events.Hidden, spectrumHidden); delete self._parentPane._isEditingStyle; delete self.originalPropertyText; } function repositionSpectrum() { spectrumHelper.reposition(colorSwatch.element); } function swatchClick(e) { if (!spectrumHelper || e.shiftKey) changeColorDisplay(e); else { var visible = spectrumHelper.toggle(colorSwatch.element, color, format); if (visible) { spectrum.displayText = color.toString(format); self.originalPropertyText = self.property.propertyText; self._parentPane._isEditingStyle = true; spectrum.addEventListener(WebInspector.Spectrum.Events.ColorChanged, spectrumChanged); spectrumHelper.addEventListener(WebInspector.SpectrumPopupHelper.Events.Hidden, spectrumHidden); scrollerElement.addEventListener("scroll", repositionSpectrum, false); } } e.consume(true); } function getFormat() { var format; var formatSetting = WebInspector.settings.colorFormat.get(); if (formatSetting === cf.Original) format = cf.Original; else if (color.nickname) format = cf.Nickname; else if (formatSetting === cf.RGB) format = (color.simple ? cf.RGB : cf.RGBA); else if (formatSetting === cf.HSL) format = (color.simple ? cf.HSL : cf.HSLA); else if (color.simple) format = (color.hasShortHex() ? cf.ShortHEX : cf.HEX); else format = cf.RGBA; return format; } var colorValueElement = document.createElement("span"); colorValueElement.textContent = color.toString(format); function nextFormat(curFormat) { switch (curFormat) { case cf.Original: return color.simple ? cf.RGB : cf.RGBA; case cf.RGB: case cf.RGBA: return color.simple ? cf.HSL : cf.HSLA; case cf.HSL: case cf.HSLA: if (color.nickname) return cf.Nickname; if (color.simple) return color.hasShortHex() ? cf.ShortHEX : cf.HEX; else return cf.Original; case cf.ShortHEX: return cf.HEX; case cf.HEX: return cf.Original; case cf.Nickname: if (color.simple) return color.hasShortHex() ? cf.ShortHEX : cf.HEX; else return cf.Original; default: return null; } } function changeColorDisplay(event) { do { format = nextFormat(format); var currentValue = color.toString(format || ""); } while (format && currentValue === color.value && format !== cf.Original); if (format) colorValueElement.textContent = currentValue; } var container = document.createElement("nobr"); container.appendChild(colorSwatch.element); container.appendChild(colorValueElement); return container; } var colorRegex = /((?:rgb|hsl)a?\([^)]+\)|#[0-9a-fA-F]{6}|#[0-9a-fA-F]{3}|\b\w+\b(?!-))/g; var colorProcessor = processValue.bind(window, colorRegex, processColor, null); valueElement.appendChild(processValue(/url\(\s*([^)\s]+)\s*\)/g, linkifyURL.bind(this), WebInspector.CSSKeywordCompletions.isColorAwareProperty(self.name) ? colorProcessor : null, value)); } this.listItemElement.removeChildren(); nameElement.normalize(); valueElement.normalize(); if (!this.treeOutline) return; if (enabledCheckboxElement && this.treeOutline.section && this.parent.root && !this.section.computedStyle) this.listItemElement.appendChild(enabledCheckboxElement); this.listItemElement.appendChild(nameElement); this.listItemElement.appendChild(document.createTextNode(": ")); this.listItemElement.appendChild(this._expandElement); this.listItemElement.appendChild(valueElement); this.listItemElement.appendChild(document.createTextNode(";")); if (!this.parsedOk) { this.hasChildren = false; this.listItemElement.addStyleClass("not-parsed-ok"); this.listItemElement.insertBefore(WebInspector.StylesSidebarPane.createExclamationMark(this.property.name), this.listItemElement.firstChild); } if (this.property.inactive) this.listItemElement.addStyleClass("inactive"); }, _updatePane: function(userCallback) { if (this.treeOutline && this.treeOutline.section && this.treeOutline.section.pane) this.treeOutline.section.pane._refreshUpdate(this.treeOutline.section, false, userCallback); else { if (userCallback) userCallback(); } }, toggleEnabled: function(event) { var disabled = !event.target.checked; function callback(newStyle) { if (!newStyle) return; this.style = newStyle; this._styleRule.style = newStyle; if (this.treeOutline.section && this.treeOutline.section.pane) this.treeOutline.section.pane.dispatchEventToListeners("style property toggled"); this._updatePane(); delete this._parentPane._userOperation; } this._parentPane._userOperation = true; this.property.setDisabled(disabled, callback.bind(this)); event.consume(); }, updateState: function() { if (!this.listItemElement) return; if (this.style.isPropertyImplicit(this.name) || this.value === "initial") this.listItemElement.addStyleClass("implicit"); else this.listItemElement.removeStyleClass("implicit"); if (this.inherited) this.listItemElement.addStyleClass("inherited"); else this.listItemElement.removeStyleClass("inherited"); if (this.overloaded) this.listItemElement.addStyleClass("overloaded"); else this.listItemElement.removeStyleClass("overloaded"); if (this.disabled) this.listItemElement.addStyleClass("disabled"); else this.listItemElement.removeStyleClass("disabled"); }, onpopulate: function() { if (this.children.length || !this.isShorthand) return; var longhandProperties = this.style.longhandProperties(this.name); for (var i = 0; i < longhandProperties.length; ++i) { var name = longhandProperties[i].name; if (this.treeOutline.section) { var inherited = this.treeOutline.section.isPropertyInherited(name); var overloaded = this.treeOutline.section.isPropertyOverloaded(name); } var liveProperty = this.style.getLiveProperty(name); if (!liveProperty) continue; var item = new WebInspector.StylePropertyTreeElement(this.section, this._parentPane, this._styleRule, this.style, liveProperty, false, inherited, overloaded); this.appendChild(item); } }, restoreNameElement: function() { if (this.nameElement === this.listItemElement.querySelector(".webkit-css-property")) return; this.nameElement = document.createElement("span"); this.nameElement.className = "webkit-css-property"; this.nameElement.textContent = ""; this.listItemElement.insertBefore(this.nameElement, this.listItemElement.firstChild); }, _mouseClick: function(event) { if (!window.getSelection().isCollapsed) return; event.consume(true); if (event.target === this.listItemElement) { if (!this.section.editable) return; if (this.section._checkWillCancelEditing()) return; this.section.addNewBlankProperty(this.property.index + 1).startEditing(); return; } this.startEditing(event.target); }, _isNameElement: function(element) { return element.enclosingNodeOrSelfWithClass("webkit-css-property") === this.nameElement; }, _isValueElement: function(element) { return !!element.enclosingNodeOrSelfWithClass("value"); }, startEditing: function(selectElement) { if (this.parent.isShorthand) return; if (selectElement === this._expandElement) return; if (this.treeOutline.section && !this.treeOutline.section.editable) return; if (!selectElement) selectElement = this.nameElement; else selectElement = selectElement.enclosingNodeOrSelfWithClass("webkit-css-property") || selectElement.enclosingNodeOrSelfWithClass("value"); var isEditingName = selectElement === this.nameElement; if (!isEditingName && selectElement !== this.valueElement) { isEditingName = false; selectElement = this.valueElement; } if (WebInspector.isBeingEdited(selectElement)) return; var context = { expanded: this.expanded, hasChildren: this.hasChildren, isEditingName: isEditingName, previousContent: selectElement.textContent }; this.hasChildren = false; if (selectElement.parentElement) selectElement.parentElement.addStyleClass("child-editing"); selectElement.textContent = selectElement.textContent; function pasteHandler(context, event) { var data = event.clipboardData.getData("Text"); if (!data) return; var colonIdx = data.indexOf(":"); if (colonIdx < 0) return; var name = data.substring(0, colonIdx).trim(); var value = data.substring(colonIdx + 1).trim(); event.preventDefault(); if (!("originalName" in context)) { context.originalName = this.nameElement.textContent; context.originalValue = this.valueElement.textContent; } this.nameElement.textContent = name; this.valueElement.textContent = value; this.nameElement.normalize(); this.valueElement.normalize(); this.editingCommitted(null, event.target.textContent, context.previousContent, context, "forward"); } function blurListener(context, event) { var treeElement = this._parentPane._mouseDownTreeElement; var moveDirection = ""; if (treeElement === this) { if (isEditingName && this._parentPane._mouseDownTreeElementIsValue) moveDirection = "forward"; if (!isEditingName && this._parentPane._mouseDownTreeElementIsName) moveDirection = "backward"; } this.editingCommitted(null, event.target.textContent, context.previousContent, context, moveDirection); } delete this.originalPropertyText; this._parentPane._isEditingStyle = true; if (selectElement.parentElement) selectElement.parentElement.scrollIntoViewIfNeeded(false); var applyItemCallback = !isEditingName ? this._applyFreeFlowStyleTextEdit.bind(this, true) : undefined; this._prompt = new WebInspector.StylesSidebarPane.CSSPropertyPrompt(isEditingName ? WebInspector.CSSCompletions.cssPropertiesMetainfo : WebInspector.CSSKeywordCompletions.forProperty(this.nameElement.textContent), this, isEditingName); if (applyItemCallback) { this._prompt.addEventListener(WebInspector.TextPrompt.Events.ItemApplied, applyItemCallback, this); this._prompt.addEventListener(WebInspector.TextPrompt.Events.ItemAccepted, applyItemCallback, this); } var proxyElement = this._prompt.attachAndStartEditing(selectElement, blurListener.bind(this, context)); proxyElement.addEventListener("keydown", this.editingNameValueKeyDown.bind(this, context), false); if (isEditingName) proxyElement.addEventListener("paste", pasteHandler.bind(this, context)); window.getSelection().setBaseAndExtent(selectElement, 0, selectElement, 1); }, editingNameValueKeyDown: function(context, event) { if (event.handled) return; var isEditingName = context.isEditingName; var result; function shouldCommitValueSemicolon(text, cursorPosition) { var openQuote = ""; for (var i = 0; i < cursorPosition; ++i) { var ch = text[i]; if (ch === "\\" && openQuote !== "") ++i; else if (!openQuote && (ch === "\"" || ch === "'")) openQuote = ch; else if (openQuote === ch) openQuote = ""; } return !openQuote; } var isFieldInputTerminated = (event.keyCode === WebInspector.KeyboardShortcut.Keys.Semicolon.code) && (isEditingName ? event.shiftKey : (!event.shiftKey && shouldCommitValueSemicolon(event.target.textContent, event.target.selectionLeftOffset()))); if (isEnterKey(event) || isFieldInputTerminated) { event.preventDefault(); result = "forward"; } else if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Esc.code || event.keyIdentifier === "U+001B") result = "cancel"; else if (!isEditingName && this._newProperty && event.keyCode === WebInspector.KeyboardShortcut.Keys.Backspace.code) { var selection = window.getSelection(); if (selection.isCollapsed && !selection.focusOffset) { event.preventDefault(); result = "backward"; } } else if (event.keyIdentifier === "U+0009") { result = event.shiftKey ? "backward" : "forward"; event.preventDefault(); } if (result) { switch (result) { case "cancel": this.editingCancelled(null, context); break; case "forward": case "backward": this.editingCommitted(null, event.target.textContent, context.previousContent, context, result); break; } event.consume(); return; } if (!isEditingName) this._applyFreeFlowStyleTextEdit(false); }, _applyFreeFlowStyleTextEdit: function(now) { if (this._applyFreeFlowStyleTextEditTimer) clearTimeout(this._applyFreeFlowStyleTextEditTimer); function apply() { var valueText = this.valueElement.textContent; if (valueText.indexOf(";") === -1) this.applyStyleText(this.nameElement.textContent + ": " + valueText, false, false, false); } if (now) apply.call(this); else this._applyFreeFlowStyleTextEditTimer = setTimeout(apply.bind(this), 100); }, kickFreeFlowStyleEditForTest: function() { this._applyFreeFlowStyleTextEdit(true); }, editingEnded: function(context) { this._resetMouseDownElement(); if (this._applyFreeFlowStyleTextEditTimer) clearTimeout(this._applyFreeFlowStyleTextEditTimer); this.hasChildren = context.hasChildren; if (context.expanded) this.expand(); var editedElement = context.isEditingName ? this.nameElement : this.valueElement; if (editedElement.parentElement) editedElement.parentElement.removeStyleClass("child-editing"); delete this._parentPane._isEditingStyle; }, editingCancelled: function(element, context) { this._removePrompt(); this._revertStyleUponEditingCanceled(this.originalPropertyText); this.editingEnded(context); }, _revertStyleUponEditingCanceled: function(originalPropertyText) { if (typeof originalPropertyText === "string") { delete this.originalPropertyText; this.applyStyleText(originalPropertyText, true, false, true); } else { if (this._newProperty) this.treeOutline.removeChild(this); else this.updateTitle(); } }, _findSibling: function(moveDirection) { var target = this; do { target = (moveDirection === "forward" ? target.nextSibling : target.previousSibling); } while(target && target.inherited); return target; }, editingCommitted: function(element, userInput, previousContent, context, moveDirection) { this._removePrompt(); this.editingEnded(context); var isEditingName = context.isEditingName; var createNewProperty, moveToPropertyName, moveToSelector; var moveTo = this; var moveToOther = (isEditingName ^ (moveDirection === "forward")); var abandonNewProperty = this._newProperty && !userInput && (moveToOther || isEditingName); if (moveDirection === "forward" && !isEditingName || moveDirection === "backward" && isEditingName) { moveTo = moveTo._findSibling(moveDirection); if (moveTo) moveToPropertyName = moveTo.name; else if (moveDirection === "forward" && (!this._newProperty || userInput)) createNewProperty = true; else if (moveDirection === "backward") moveToSelector = true; } var moveToIndex = moveTo && this.treeOutline ? this.treeOutline.children.indexOf(moveTo) : -1; var blankInput = /^\s*$/.test(userInput); var isDataPasted = "originalName" in context; var isDirtyViaPaste = isDataPasted && (this.nameElement.textContent !== context.originalName || this.valueElement.textContent !== context.originalValue); var shouldCommitNewProperty = this._newProperty && (moveToOther || (!moveDirection && !isEditingName) || (isEditingName && blankInput)); if (((userInput !== previousContent || isDirtyViaPaste) && !this._newProperty) || shouldCommitNewProperty) { this.treeOutline.section._afterUpdate = moveToNextCallback.bind(this, this._newProperty, !blankInput, this.treeOutline.section); var propertyText; if (blankInput || (this._newProperty && /^\s*$/.test(this.valueElement.textContent))) propertyText = ""; else { if (isEditingName) propertyText = userInput + ": " + this.valueElement.textContent; else propertyText = this.nameElement.textContent + ": " + userInput; } this.applyStyleText(propertyText, true, true, false); } else { if (!isDataPasted && !this._newProperty) this.updateTitle(); moveToNextCallback.call(this, this._newProperty, false, this.treeOutline.section); } function moveToNextCallback(alreadyNew, valueChanged, section) { if (!moveDirection) return; if (moveTo && moveTo.parent) { moveTo.startEditing(!isEditingName ? moveTo.nameElement : moveTo.valueElement); return; } if (moveTo && !moveTo.parent) { var propertyElements = section.propertiesTreeOutline.children; if (moveDirection === "forward" && blankInput && !isEditingName) --moveToIndex; if (moveToIndex >= propertyElements.length && !this._newProperty) createNewProperty = true; else { var treeElement = moveToIndex >= 0 ? propertyElements[moveToIndex] : null; if (treeElement) { var elementToEdit = !isEditingName ? treeElement.nameElement : treeElement.valueElement; if (alreadyNew && blankInput) elementToEdit = moveDirection === "forward" ? treeElement.nameElement : treeElement.valueElement; treeElement.startEditing(elementToEdit); return; } else if (!alreadyNew) moveToSelector = true; } } if (createNewProperty) { if (alreadyNew && !valueChanged && (isEditingName ^ (moveDirection === "backward"))) return; section.addNewBlankProperty().startEditing(); return; } if (abandonNewProperty) { moveTo = this._findSibling(moveDirection); var sectionToEdit = (moveTo || moveDirection === "backward") ? section : section.nextEditableSibling(); if (sectionToEdit) { if (sectionToEdit.rule) sectionToEdit.startEditingSelector(); else sectionToEdit._moveEditorFromSelector(moveDirection); } return; } if (moveToSelector) { if (section.rule) section.startEditingSelector(); else section._moveEditorFromSelector(moveDirection); } } }, _removePrompt: function() { if (this._prompt) { this._prompt.detach(); delete this._prompt; } }, _hasBeenModifiedIncrementally: function() { return typeof this.originalPropertyText === "string" || (!!this.property.propertyText && this._newProperty); }, applyStyleText: function(styleText, updateInterface, majorChange, isRevert) { function userOperationFinishedCallback(parentPane, updateInterface) { if (updateInterface) delete parentPane._userOperation; } if (!isRevert && !updateInterface && !this._hasBeenModifiedIncrementally()) { this.originalPropertyText = this.property.propertyText; } if (!this.treeOutline) return; var section = this.treeOutline.section; styleText = styleText.replace(/\s/g, " ").trim(); var styleTextLength = styleText.length; if (!styleTextLength && updateInterface && !isRevert && this._newProperty && !this._hasBeenModifiedIncrementally()) { this.parent.removeChild(this); section.afterUpdate(); return; } var currentNode = this._parentPane.node; if (updateInterface) this._parentPane._userOperation = true; function callback(userCallback, originalPropertyText, newStyle) { if (!newStyle) { if (updateInterface) { this._revertStyleUponEditingCanceled(originalPropertyText); } userCallback(); return; } if (this._newProperty) this._newPropertyInStyle = true; this.style = newStyle; this.property = newStyle.propertyAt(this.property.index); this._styleRule.style = this.style; if (section && section.pane) section.pane.dispatchEventToListeners("style edited"); if (updateInterface && currentNode === section.pane.node) { this._updatePane(userCallback); return; } userCallback(); } if (styleText.length && !/;\s*$/.test(styleText)) styleText += ";"; var overwriteProperty = !!(!this._newProperty || this._newPropertyInStyle); this.property.setText(styleText, majorChange, overwriteProperty, callback.bind(this, userOperationFinishedCallback.bind(null, this._parentPane, updateInterface), this.originalPropertyText)); }, ondblclick: function() { return true; }, isEventWithinDisclosureTriangle: function(event) { if (!this.section.computedStyle) return event.target === this._expandElement; return TreeElement.prototype.isEventWithinDisclosureTriangle.call(this, event); }, __proto__: TreeElement.prototype } WebInspector.StylesSidebarPane.CSSPropertyPrompt = function(cssCompletions, sidebarPane, isEditingName, acceptCallback) { WebInspector.TextPrompt.call(this, this._buildPropertyCompletions.bind(this), WebInspector.StyleValueDelimiters); this.setSuggestBoxEnabled("generic-suggest"); this._cssCompletions = cssCompletions; this._sidebarPane = sidebarPane; this._isEditingName = isEditingName; } WebInspector.StylesSidebarPane.CSSPropertyPrompt.prototype = { onKeyDown: function(event) { switch (event.keyIdentifier) { case "Up": case "Down": case "PageUp": case "PageDown": if (this._handleNameOrValueUpDown(event)) { event.preventDefault(); return; } break; } WebInspector.TextPrompt.prototype.onKeyDown.call(this, event); }, onMouseWheel: function(event) { if (this._handleNameOrValueUpDown(event)) { event.consume(true); return; } WebInspector.TextPrompt.prototype.onMouseWheel.call(this, event); }, tabKeyPressed: function() { this.acceptAutoComplete(); return false; }, _handleNameOrValueUpDown: function(event) { function finishHandler(originalValue, replacementString) { this._sidebarPane.applyStyleText(this._sidebarPane.nameElement.textContent + ": " + this._sidebarPane.valueElement.textContent, false, false, false); } if (!this._isEditingName && WebInspector.handleElementValueModifications(event, this._sidebarPane.valueElement, finishHandler.bind(this), this._isValueSuggestion.bind(this))) return true; return false; }, _isValueSuggestion: function(word) { if (!word) return false; word = word.toLowerCase(); return this._cssCompletions.keySet().hasOwnProperty(word); }, _buildPropertyCompletions: function(proxyElement, wordRange, force, completionsReadyCallback) { var prefix = wordRange.toString().toLowerCase(); if (!prefix && !force) return; var results = this._cssCompletions.startsWith(prefix); var selectedIndex = this._cssCompletions.mostUsedOf(results); completionsReadyCallback(results, selectedIndex); }, __proto__: WebInspector.TextPrompt.prototype } ; WebInspector.ElementsPanel = function() { WebInspector.Panel.call(this, "elements"); this.registerRequiredCSS("breadcrumbList.css"); this.registerRequiredCSS("elementsPanel.css"); this.registerRequiredCSS("textPrompt.css"); this.setHideOnDetach(); const initialSidebarWidth = 325; const minimumContentWidthPercent = 34; this.createSidebarView(this.element, WebInspector.SidebarView.SidebarPosition.Right, initialSidebarWidth); this.splitView.setMinimumSidebarWidth(Preferences.minElementsSidebarWidth); this.splitView.setMinimumMainWidthPercent(minimumContentWidthPercent); this.contentElement = this.splitView.mainElement; this.contentElement.id = "elements-content"; this.contentElement.addStyleClass("outline-disclosure"); this.contentElement.addStyleClass("source-code"); if (!WebInspector.settings.domWordWrap.get()) this.contentElement.classList.add("nowrap"); WebInspector.settings.domWordWrap.addChangeListener(this._domWordWrapSettingChanged.bind(this)); this.contentElement.addEventListener("contextmenu", this._contextMenuEventFired.bind(this), true); this.treeOutline = new WebInspector.ElementsTreeOutline(true, true, false, this._populateContextMenu.bind(this), this._setPseudoClassForNodeId.bind(this)); this.treeOutline.wireToDomAgent(); this.treeOutline.addEventListener(WebInspector.ElementsTreeOutline.Events.SelectedNodeChanged, this._selectedNodeChanged, this); this.crumbsElement = document.createElement("div"); this.crumbsElement.className = "crumbs"; this.crumbsElement.addEventListener("mousemove", this._mouseMovedInCrumbs.bind(this), false); this.crumbsElement.addEventListener("mouseout", this._mouseMovedOutOfCrumbs.bind(this), false); this.sidebarPanes = {}; this.sidebarPanes.computedStyle = new WebInspector.ComputedStyleSidebarPane(); this.sidebarPanes.styles = new WebInspector.StylesSidebarPane(this.sidebarPanes.computedStyle, this._setPseudoClassForNodeId.bind(this)); this.sidebarPanes.metrics = new WebInspector.MetricsSidebarPane(); this.sidebarPanes.properties = new WebInspector.PropertiesSidebarPane(); this.sidebarPanes.domBreakpoints = WebInspector.domBreakpointsSidebarPane; this.sidebarPanes.eventListeners = new WebInspector.EventListenersSidebarPane(); this.sidebarPanes.styles.onexpand = this.updateStyles.bind(this); this.sidebarPanes.metrics.onexpand = this.updateMetrics.bind(this); this.sidebarPanes.properties.onexpand = this.updateProperties.bind(this); this.sidebarPanes.eventListeners.onexpand = this.updateEventListeners.bind(this); this.sidebarPanes.styles.expanded = true; this.sidebarPanes.styles.addEventListener("style edited", this._stylesPaneEdited, this); this.sidebarPanes.styles.addEventListener("style property toggled", this._stylesPaneEdited, this); this.sidebarPanes.metrics.addEventListener("metrics edited", this._metricsPaneEdited, this); for (var pane in this.sidebarPanes) { this.sidebarElement.appendChild(this.sidebarPanes[pane].element); if (this.sidebarPanes[pane].onattach) this.sidebarPanes[pane].onattach(); } this._registerShortcuts(); this._popoverHelper = new WebInspector.PopoverHelper(this.element, this._getPopoverAnchor.bind(this), this._showPopover.bind(this)); this._popoverHelper.setTimeout(0); WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.AttrModified, this._updateBreadcrumbIfNeeded, this); WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.AttrRemoved, this._updateBreadcrumbIfNeeded, this); WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.NodeRemoved, this._nodeRemoved, this); WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.DocumentUpdated, this._documentUpdatedEvent, this); WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.InspectElementRequested, this._inspectElementRequested, this); if (WebInspector.domAgent.existingDocument()) this._documentUpdated(WebInspector.domAgent.existingDocument()); } WebInspector.ElementsPanel.prototype = { get statusBarItems() { return [this.crumbsElement]; }, defaultFocusedElement: function() { return this.treeOutline.element; }, statusBarResized: function() { this.updateBreadcrumbSizes(); }, wasShown: function() { if (this.treeOutline.element.parentElement !== this.contentElement) this.contentElement.appendChild(this.treeOutline.element); WebInspector.Panel.prototype.wasShown.call(this); this.updateBreadcrumb(); this.treeOutline.updateSelection(); this.treeOutline.setVisible(true); if (!this.treeOutline.rootDOMNode) WebInspector.domAgent.requestDocument(); this.sidebarElement.insertBefore(this.sidebarPanes.domBreakpoints.element, this.sidebarPanes.eventListeners.element); }, willHide: function() { WebInspector.domAgent.hideDOMNodeHighlight(); this.treeOutline.setVisible(false); this._popoverHelper.hidePopover(); this.contentElement.removeChild(this.treeOutline.element); for (var pane in this.sidebarPanes) { if (this.sidebarPanes[pane].willHide) this.sidebarPanes[pane].willHide(); } WebInspector.Panel.prototype.willHide.call(this); }, onResize: function() { this.treeOutline.updateSelection(); this.updateBreadcrumbSizes(); }, _setPseudoClassForNodeId: function(nodeId, pseudoClass, enable) { var node = WebInspector.domAgent.nodeForId(nodeId); if (!node) return; var pseudoClasses = node.getUserProperty(WebInspector.ElementsTreeOutline.PseudoStateDecorator.PropertyName); if (enable) { pseudoClasses = pseudoClasses || []; if (pseudoClasses.indexOf(pseudoClass) >= 0) return; pseudoClasses.push(pseudoClass); node.setUserProperty(WebInspector.ElementsTreeOutline.PseudoStateDecorator.PropertyName, pseudoClasses); } else { if (!pseudoClasses || pseudoClasses.indexOf(pseudoClass) < 0) return; pseudoClasses.remove(pseudoClass); if (!pseudoClasses.length) node.removeUserProperty(WebInspector.ElementsTreeOutline.PseudoStateDecorator.PropertyName); } this.treeOutline.updateOpenCloseTags(node); WebInspector.cssModel.forcePseudoState(node.id, node.getUserProperty(WebInspector.ElementsTreeOutline.PseudoStateDecorator.PropertyName)); this._metricsPaneEdited(); this._stylesPaneEdited(); }, _selectedNodeChanged: function() { var selectedNode = this.selectedDOMNode(); if (!selectedNode && this._lastValidSelectedNode) this._selectedPathOnReset = this._lastValidSelectedNode.path(); this.updateBreadcrumb(false); this._updateSidebars(); if (selectedNode) { ConsoleAgent.addInspectedNode(selectedNode.id); this._lastValidSelectedNode = selectedNode; } WebInspector.notifications.dispatchEventToListeners(WebInspector.ElementsTreeOutline.Events.SelectedNodeChanged); }, _updateSidebars: function() { for (var pane in this.sidebarPanes) this.sidebarPanes[pane].needsUpdate = true; this.updateStyles(true); this.updateMetrics(); this.updateProperties(); this.updateEventListeners(); }, _reset: function() { delete this.currentQuery; }, _documentUpdatedEvent: function(event) { this._documentUpdated(event.data); }, _documentUpdated: function(inspectedRootDocument) { this._reset(); this.searchCanceled(); this.treeOutline.rootDOMNode = inspectedRootDocument; if (!inspectedRootDocument) { if (this.isShowing()) WebInspector.domAgent.requestDocument(); return; } this.sidebarPanes.domBreakpoints.restoreBreakpoints(); function selectNode(candidateFocusNode) { if (!candidateFocusNode) candidateFocusNode = inspectedRootDocument.body || inspectedRootDocument.documentElement; if (!candidateFocusNode) return; this.selectDOMNode(candidateFocusNode); if (this.treeOutline.selectedTreeElement) this.treeOutline.selectedTreeElement.expand(); } function selectLastSelectedNode(nodeId) { if (this.selectedDOMNode()) { return; } var node = nodeId ? WebInspector.domAgent.nodeForId(nodeId) : null; selectNode.call(this, node); } if (this._selectedPathOnReset) WebInspector.domAgent.pushNodeByPathToFrontend(this._selectedPathOnReset, selectLastSelectedNode.bind(this)); else selectNode.call(this); delete this._selectedPathOnReset; }, searchCanceled: function() { delete this._searchQuery; this._hideSearchHighlights(); WebInspector.searchController.updateSearchMatchesCount(0, this); delete this._currentSearchResultIndex; delete this._searchResults; WebInspector.domAgent.cancelSearch(); }, performSearch: function(query) { this.searchCanceled(); const whitespaceTrimmedQuery = query.trim(); if (!whitespaceTrimmedQuery.length) return; this._searchQuery = query; function resultCountCallback(resultCount) { WebInspector.searchController.updateSearchMatchesCount(resultCount, this); if (!resultCount) return; this._searchResults = new Array(resultCount); this._currentSearchResultIndex = -1; this.jumpToNextSearchResult(); } WebInspector.domAgent.performSearch(whitespaceTrimmedQuery, resultCountCallback.bind(this)); }, _contextMenuEventFired: function(event) { function toggleWordWrap() { WebInspector.settings.domWordWrap.set(!WebInspector.settings.domWordWrap.get()); } var contextMenu = new WebInspector.ContextMenu(event); var populated = this.treeOutline.populateContextMenu(contextMenu, event); if (WebInspector.experimentsSettings.cssRegions.isEnabled()) { contextMenu.appendSeparator(); contextMenu.appendItem(WebInspector.UIString("CSS Named Flows..."), this._showNamedFlowCollections.bind(this)); } contextMenu.appendSeparator(); contextMenu.appendCheckboxItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Word wrap" : "Word Wrap"), toggleWordWrap.bind(this), WebInspector.settings.domWordWrap.get()); contextMenu.show(); }, _showNamedFlowCollections: function() { if (!WebInspector.cssNamedFlowCollectionsView) WebInspector.cssNamedFlowCollectionsView = new WebInspector.CSSNamedFlowCollectionsView(); WebInspector.cssNamedFlowCollectionsView.showInDrawer(); }, _domWordWrapSettingChanged: function(event) { if (event.data) this.contentElement.removeStyleClass("nowrap"); else this.contentElement.addStyleClass("nowrap"); var selectedNode = this.selectedDOMNode(); if (!selectedNode) return; var treeElement = this.treeOutline.findTreeElement(selectedNode); if (treeElement) treeElement.updateSelection(); }, switchToAndFocus: function(node) { WebInspector.searchController.cancelSearch(); WebInspector.inspectorView.setCurrentPanel(this); this.selectDOMNode(node, true); }, _populateContextMenu: function(contextMenu, node) { contextMenu.appendSeparator(); var pane = this.sidebarPanes.domBreakpoints; pane.populateNodeContextMenu(node, contextMenu); }, _getPopoverAnchor: function(element) { var anchor = element.enclosingNodeOrSelfWithClass("webkit-html-resource-link"); if (anchor) { if (!anchor.href) return null; var resource = WebInspector.resourceTreeModel.resourceForURL(anchor.href); if (!resource || resource.type !== WebInspector.resourceTypes.Image) return null; anchor.removeAttribute("title"); } return anchor; }, _loadDimensionsForNode: function(treeElement, callback) { if (treeElement.treeOutline !== this.treeOutline) { callback(); return; } var node = (treeElement.representedObject); if (!node.nodeName() || node.nodeName().toLowerCase() !== "img") { callback(); return; } WebInspector.RemoteObject.resolveNode(node, "", resolvedNode); function resolvedNode(object) { if (!object) { callback(); return; } object.callFunctionJSON(dimensions, undefined, callback); object.release(); function dimensions() { return { offsetWidth: this.offsetWidth, offsetHeight: this.offsetHeight, naturalWidth: this.naturalWidth, naturalHeight: this.naturalHeight }; } } }, _showPopover: function(anchor, popover) { var listItem = anchor.enclosingNodeOrSelfWithNodeName("li"); if (listItem && listItem.treeElement) this._loadDimensionsForNode(listItem.treeElement, WebInspector.DOMPresentationUtils.buildImagePreviewContents.bind(WebInspector.DOMPresentationUtils, anchor.href, true, showPopover)); else WebInspector.DOMPresentationUtils.buildImagePreviewContents(anchor.href, true, showPopover); function showPopover(contents) { if (!contents) return; popover.setCanShrink(false); popover.show(contents, anchor); } }, jumpToNextSearchResult: function() { if (!this._searchResults) return; this._hideSearchHighlights(); if (++this._currentSearchResultIndex >= this._searchResults.length) this._currentSearchResultIndex = 0; this._highlightCurrentSearchResult(); }, jumpToPreviousSearchResult: function() { if (!this._searchResults) return; this._hideSearchHighlights(); if (--this._currentSearchResultIndex < 0) this._currentSearchResultIndex = (this._searchResults.length - 1); this._highlightCurrentSearchResult(); return true; }, _highlightCurrentSearchResult: function() { var index = this._currentSearchResultIndex; var searchResults = this._searchResults; var searchResult = searchResults[index]; if (searchResult === null) { WebInspector.searchController.updateCurrentMatchIndex(index, this); return; } if (typeof searchResult === "undefined") { function callback(node) { searchResults[index] = node || null; this._highlightCurrentSearchResult(); } WebInspector.domAgent.searchResult(index, callback.bind(this)); return; } WebInspector.searchController.updateCurrentMatchIndex(index, this); var treeElement = this.treeOutline.findTreeElement(searchResult); if (treeElement) { treeElement.highlightSearchResults(this._searchQuery); treeElement.reveal(); } }, _hideSearchHighlights: function() { if (!this._searchResults) return; var searchResult = this._searchResults[this._currentSearchResultIndex]; if (!searchResult) return; var treeElement = this.treeOutline.findTreeElement(searchResult); if (treeElement) treeElement.hideSearchHighlights(); }, selectedDOMNode: function() { return this.treeOutline.selectedDOMNode(); }, selectDOMNode: function(node, focus) { this.treeOutline.selectDOMNode(node, focus); }, _nodeRemoved: function(event) { if (!this.isShowing()) return; var crumbs = this.crumbsElement; for (var crumb = crumbs.firstChild; crumb; crumb = crumb.nextSibling) { if (crumb.representedObject === event.data.node) { this.updateBreadcrumb(true); return; } } }, _stylesPaneEdited: function() { this.sidebarPanes.metrics.needsUpdate = true; this.updateMetrics(); }, _metricsPaneEdited: function() { this.sidebarPanes.styles.needsUpdate = true; this.updateStyles(true); }, _mouseMovedInCrumbs: function(event) { var nodeUnderMouse = document.elementFromPoint(event.pageX, event.pageY); var crumbElement = nodeUnderMouse.enclosingNodeOrSelfWithClass("crumb"); WebInspector.domAgent.highlightDOMNode(crumbElement ? crumbElement.representedObject.id : 0); if ("_mouseOutOfCrumbsTimeout" in this) { clearTimeout(this._mouseOutOfCrumbsTimeout); delete this._mouseOutOfCrumbsTimeout; } }, _mouseMovedOutOfCrumbs: function(event) { var nodeUnderMouse = document.elementFromPoint(event.pageX, event.pageY); if (nodeUnderMouse && nodeUnderMouse.isDescendant(this.crumbsElement)) return; WebInspector.domAgent.hideDOMNodeHighlight(); this._mouseOutOfCrumbsTimeout = setTimeout(this.updateBreadcrumbSizes.bind(this), 1000); }, _updateBreadcrumbIfNeeded: function(event) { var name = event.data.name; if (name !== "class" && name !== "id") return; var node = (event.data.node); var crumbs = this.crumbsElement; var crumb = crumbs.firstChild; while (crumb) { if (crumb.representedObject === node) { this.updateBreadcrumb(true); break; } crumb = crumb.nextSibling; } }, updateBreadcrumb: function(forceUpdate) { if (!this.isShowing()) return; var crumbs = this.crumbsElement; var handled = false; var crumb = crumbs.firstChild; while (crumb) { if (crumb.representedObject === this.selectedDOMNode()) { crumb.addStyleClass("selected"); handled = true; } else { crumb.removeStyleClass("selected"); } crumb = crumb.nextSibling; } if (handled && !forceUpdate) { this.updateBreadcrumbSizes(); return; } crumbs.removeChildren(); var panel = this; function selectCrumbFunction(event) { var crumb = event.currentTarget; if (crumb.hasStyleClass("collapsed")) { if (crumb === panel.crumbsElement.firstChild) { var currentCrumb = crumb; while (currentCrumb) { var hidden = currentCrumb.hasStyleClass("hidden"); var collapsed = currentCrumb.hasStyleClass("collapsed"); if (!hidden && !collapsed) break; crumb = currentCrumb; currentCrumb = currentCrumb.nextSibling; } } panel.updateBreadcrumbSizes(crumb); } else panel.selectDOMNode(crumb.representedObject, true); event.preventDefault(); } for (var current = this.selectedDOMNode(); current; current = current.parentNode) { if (current.nodeType() === Node.DOCUMENT_NODE) continue; crumb = document.createElement("span"); crumb.className = "crumb"; crumb.representedObject = current; crumb.addEventListener("mousedown", selectCrumbFunction, false); var crumbTitle; switch (current.nodeType()) { case Node.ELEMENT_NODE: WebInspector.DOMPresentationUtils.decorateNodeLabel(current, crumb); break; case Node.TEXT_NODE: crumbTitle = WebInspector.UIString("(text)"); break case Node.COMMENT_NODE: crumbTitle = "<!-->"; break; case Node.DOCUMENT_TYPE_NODE: crumbTitle = "<!DOCTYPE>"; break; default: crumbTitle = current.nodeNameInCorrectCase(); } if (!crumb.childNodes.length) { var nameElement = document.createElement("span"); nameElement.textContent = crumbTitle; crumb.appendChild(nameElement); crumb.title = crumbTitle; } if (current === this.selectedDOMNode()) crumb.addStyleClass("selected"); if (!crumbs.childNodes.length) crumb.addStyleClass("end"); crumbs.appendChild(crumb); } if (crumbs.hasChildNodes()) crumbs.lastChild.addStyleClass("start"); this.updateBreadcrumbSizes(); }, updateBreadcrumbSizes: function(focusedCrumb) { if (!this.isShowing()) return; if (document.body.offsetWidth <= 0) { return; } var crumbs = this.crumbsElement; if (!crumbs.childNodes.length || crumbs.offsetWidth <= 0) return; var selectedIndex = 0; var focusedIndex = 0; var selectedCrumb; var i = 0; var crumb = crumbs.firstChild; while (crumb) { if (!selectedCrumb && crumb.hasStyleClass("selected")) { selectedCrumb = crumb; selectedIndex = i; } if (crumb === focusedCrumb) focusedIndex = i; if (crumb !== crumbs.lastChild) crumb.removeStyleClass("start"); if (crumb !== crumbs.firstChild) crumb.removeStyleClass("end"); crumb.removeStyleClass("compact"); crumb.removeStyleClass("collapsed"); crumb.removeStyleClass("hidden"); crumb = crumb.nextSibling; ++i; } crumbs.firstChild.addStyleClass("end"); crumbs.lastChild.addStyleClass("start"); function crumbsAreSmallerThanContainer() { var rightPadding = 20; var errorWarningElement = document.getElementById("error-warning-count"); if (!WebInspector.drawer.visible && errorWarningElement) rightPadding += errorWarningElement.offsetWidth; return ((crumbs.totalOffsetLeft() + crumbs.offsetWidth + rightPadding) < window.innerWidth); } if (crumbsAreSmallerThanContainer()) return; var BothSides = 0; var AncestorSide = -1; var ChildSide = 1; function makeCrumbsSmaller(shrinkingFunction, direction, significantCrumb) { if (!significantCrumb) significantCrumb = (focusedCrumb || selectedCrumb); if (significantCrumb === selectedCrumb) var significantIndex = selectedIndex; else if (significantCrumb === focusedCrumb) var significantIndex = focusedIndex; else { var significantIndex = 0; for (var i = 0; i < crumbs.childNodes.length; ++i) { if (crumbs.childNodes[i] === significantCrumb) { significantIndex = i; break; } } } function shrinkCrumbAtIndex(index) { var shrinkCrumb = crumbs.childNodes[index]; if (shrinkCrumb && shrinkCrumb !== significantCrumb) shrinkingFunction(shrinkCrumb); if (crumbsAreSmallerThanContainer()) return true; return false; } if (direction) { var index = (direction > 0 ? 0 : crumbs.childNodes.length - 1); while (index !== significantIndex) { if (shrinkCrumbAtIndex(index)) return true; index += (direction > 0 ? 1 : -1); } } else { var startIndex = 0; var endIndex = crumbs.childNodes.length - 1; while (startIndex != significantIndex || endIndex != significantIndex) { var startDistance = significantIndex - startIndex; var endDistance = endIndex - significantIndex; if (startDistance >= endDistance) var index = startIndex++; else var index = endIndex--; if (shrinkCrumbAtIndex(index)) return true; } } return false; } function coalesceCollapsedCrumbs() { var crumb = crumbs.firstChild; var collapsedRun = false; var newStartNeeded = false; var newEndNeeded = false; while (crumb) { var hidden = crumb.hasStyleClass("hidden"); if (!hidden) { var collapsed = crumb.hasStyleClass("collapsed"); if (collapsedRun && collapsed) { crumb.addStyleClass("hidden"); crumb.removeStyleClass("compact"); crumb.removeStyleClass("collapsed"); if (crumb.hasStyleClass("start")) { crumb.removeStyleClass("start"); newStartNeeded = true; } if (crumb.hasStyleClass("end")) { crumb.removeStyleClass("end"); newEndNeeded = true; } continue; } collapsedRun = collapsed; if (newEndNeeded) { newEndNeeded = false; crumb.addStyleClass("end"); } } else collapsedRun = true; crumb = crumb.nextSibling; } if (newStartNeeded) { crumb = crumbs.lastChild; while (crumb) { if (!crumb.hasStyleClass("hidden")) { crumb.addStyleClass("start"); break; } crumb = crumb.previousSibling; } } } function compact(crumb) { if (crumb.hasStyleClass("hidden")) return; crumb.addStyleClass("compact"); } function collapse(crumb, dontCoalesce) { if (crumb.hasStyleClass("hidden")) return; crumb.addStyleClass("collapsed"); crumb.removeStyleClass("compact"); if (!dontCoalesce) coalesceCollapsedCrumbs(); } if (!focusedCrumb) { if (makeCrumbsSmaller(compact, ChildSide)) return; if (makeCrumbsSmaller(collapse, ChildSide)) return; } if (makeCrumbsSmaller(compact, (focusedCrumb ? BothSides : AncestorSide))) return; if (makeCrumbsSmaller(collapse, (focusedCrumb ? BothSides : AncestorSide))) return; if (!selectedCrumb) return; compact(selectedCrumb); if (crumbsAreSmallerThanContainer()) return; collapse(selectedCrumb, true); }, updateStyles: function(forceUpdate) { var stylesSidebarPane = this.sidebarPanes.styles; var computedStylePane = this.sidebarPanes.computedStyle; if ((!stylesSidebarPane.expanded && !computedStylePane.expanded) || !stylesSidebarPane.needsUpdate) return; stylesSidebarPane.update(this.selectedDOMNode(), forceUpdate); stylesSidebarPane.needsUpdate = false; }, updateMetrics: function() { var metricsSidebarPane = this.sidebarPanes.metrics; if (!metricsSidebarPane.expanded || !metricsSidebarPane.needsUpdate) return; metricsSidebarPane.update(this.selectedDOMNode()); metricsSidebarPane.needsUpdate = false; }, updateProperties: function() { var propertiesSidebarPane = this.sidebarPanes.properties; if (!propertiesSidebarPane.expanded || !propertiesSidebarPane.needsUpdate) return; propertiesSidebarPane.update(this.selectedDOMNode()); propertiesSidebarPane.needsUpdate = false; }, updateEventListeners: function() { var eventListenersSidebarPane = this.sidebarPanes.eventListeners; if (!eventListenersSidebarPane.expanded || !eventListenersSidebarPane.needsUpdate) return; eventListenersSidebarPane.update(this.selectedDOMNode()); eventListenersSidebarPane.needsUpdate = false; }, _registerShortcuts: function() { var shortcut = WebInspector.KeyboardShortcut; var section = WebInspector.shortcutsScreen.section(WebInspector.UIString("Elements Panel")); var keys = [ shortcut.shortcutToString(shortcut.Keys.Up), shortcut.shortcutToString(shortcut.Keys.Down) ]; section.addRelatedKeys(keys, WebInspector.UIString("Navigate elements")); keys = [ shortcut.shortcutToString(shortcut.Keys.Right), shortcut.shortcutToString(shortcut.Keys.Left) ]; section.addRelatedKeys(keys, WebInspector.UIString("Expand/collapse")); section.addKey(shortcut.shortcutToString(shortcut.Keys.Enter), WebInspector.UIString("Edit attribute")); section.addKey(shortcut.shortcutToString(shortcut.Keys.F2), WebInspector.UIString("Toggle edit as HTML")); this.sidebarPanes.styles.registerShortcuts(); }, handleShortcut: function(event) { if (WebInspector.KeyboardShortcut.eventHasCtrlOrMeta(event) && !event.shiftKey && event.keyIdentifier === "U+005A") { WebInspector.domAgent.undo(this._updateSidebars.bind(this)); event.handled = true; return; } var isRedoKey = WebInspector.isMac() ? event.metaKey && event.shiftKey && event.keyIdentifier === "U+005A" : event.ctrlKey && event.keyIdentifier === "U+0059"; if (isRedoKey) { DOMAgent.redo(this._updateSidebars.bind(this)); event.handled = true; return; } this.treeOutline.handleShortcut(event); }, handleCopyEvent: function(event) { if (!window.getSelection().isCollapsed) return; event.clipboardData.clearData(); event.preventDefault(); this.selectedDOMNode().copyNode(); }, sidebarResized: function(event) { this.treeOutline.updateSelection(); }, _inspectElementRequested: function(event) { var node = event.data; this.revealAndSelectNode(node.id); }, revealAndSelectNode: function(nodeId) { WebInspector.inspectorView.setCurrentPanel(this); var node = WebInspector.domAgent.nodeForId(nodeId); if (!node) return; WebInspector.domAgent.highlightDOMNodeForTwoSeconds(nodeId); this.selectDOMNode(node, true); }, appendApplicableItems: function(event, contextMenu, target) { if (!(target instanceof WebInspector.RemoteObject)) return; var remoteObject = (target); if (remoteObject.subtype !== "node") return; function selectNode(nodeId) { if (nodeId) WebInspector.domAgent.inspectElement(nodeId); } function revealElement() { remoteObject.pushNodeToFrontend(selectNode); } contextMenu.appendItem(WebInspector.UIString("Reveal in Elements Panel"), revealElement.bind(this)); }, __proto__: WebInspector.Panel.prototype }